Linux有一个函数调用跟踪器。我建议您跟踪IO请求。
警告:以下内容是我写的,没有真正知道具体细节。
基本上,您需要使用PCI API与磁盘设备进行对话以设置直接内存访问,因为您不想一次读取一个字节的磁盘块(或以太网帧)。因此,您告诉硬件,内存的某些区域(从地址X开始,长度为N字节)是DMA区域。您还可以设置内存缓存,以了解RAM区域中的数据可以更改而无需CPU写入,因此即使您是单处理器,它也是易失的。
假设硬件一次仅支持一个DMA事务。然后,您发送诸如“读取512字节的扇区号X(即字节X << 9到磁盘的((X + 1)<< 9)-1)字节)并将其放入DMA区域的命令。完成后,触发中断”。磁盘控制器完成其工作(它具有ARM CPU和所有功能),通过PCI与北桥集线器进行通信,并通过它与RAM进行通信,从而绕过CPU。写入完成(或出现错误)后,将触发中断。发生这种情况时,您需要等待(嗯,内核在进程睡眠时会运行其他进程)。数百万个CPU周期(10ms是2Ghz芯片的永恒时间)之后,将触发中断。通知操作系统读取已完成。操作系统可以在RAM中看到数据。然后,它可以将其复制到用户进程内存中,也可以将其复制到共享页中,并且用户进程可以从那里读取它。恢复用户进程(好吧,将其置于准备运行队列中,并在调度程序感到满意时最终运行)。
通过将数据复制到DMA空间并传输“将数据从DMA区域写入磁盘上的扇区号X,并在完成后触发中断”命令来进行写入工作。然后,磁盘在完成写入操作或从RAM读取数据后可能会触发中断,在这种情况下,fsync不能真正起作用,并且电源故障会损坏数据库和文件系统。
OS块高速缓存可在整个4KB内存页面上工作,因此一次读取8个扇区,但是想法是相同的。新磁盘具有适用于4KB扇区的本机API ,但想法是相同的。USB与PCI不同,但是想法是相同的。各种高性能硬件具有用于加速所有这些的聪明的API,同时具有多个正在运行的事务以及对其订购的各种控制。
卸载TCP / IP的网络接口可能在数据包周围有一个API,而不是以太网帧,因为NIC可以理解TCP / IP标头。
真正是网络设备的块设备会将翻译隐藏在某个地方(部分包含在硬件中,部分包含在固件中,部分包含在软件中)。
在Linux中,对于我的硬件,我认为它是这样的:
加载模块sata_piix时,它会告诉操作系统其支持的设备的PCI设备ID以及操作系统应使用的回调,所有这些都在结构中进行了描述。通用OS PCI拓扑代码发现ID为8086:27c0的设备(ICH7),并在驱动程序表中找到该设备,因此OS决定这是该硬件的正确驱动程序。在该表中,驱动程序将发现它以后应将该设备视为ICH6 SATA设备。由于驱动程序说它支持设备,因此OS 向驱动程序注册了设备。
从那里分配并准备设备的控制区域。DMA 已建立。启用了PCI总线 主控功能(这允许控制器自行启动向RAM的PCI数据传输(当数据准备就绪时),而不是等待CPU启动传输)。设置了中断处理程序。
该代码是通用代码,按时间顺序支持多代硬件:
因此很难阅读。跟踪将使其变得更加容易。