前面我们了解到,cpu通过读写io地址来读取磁盘扇区里的数据,我们又了解到cpu与磁盘之间可能隔着前端总线,北桥芯片,南北桥之间的pci连接,以及南桥上磁盘控制器,最后才能到达磁盘驱动器控制磁头读写磁盘数据。现在我们将这几个场景连接起来,看看更具体一点的交互过程。

首先,我们打开windows系统里的设备管理器,找到磁盘控制器和磁盘驱动器两个设备。这两个设备的名字容易引起混淆。我们看这两个设备的属性,我们看到磁盘控制器属性里赫然写着pci地址,如位置:PCI总线0,设备31,功能号2。也就是说我们的磁盘控制器其实是一个pci设备,连在pci总线上,pci总线最终连着北桥即host主桥。

既然是pci设备就有pci地址空间,而这个地址空间会由host主桥将其映射到存储空间。cpu其实是通过host主桥来访问pci地址空间。pci总线的工作原理我们以后再详细研究。现在我们知道一点,所谓的磁盘控制器其实可能就是一个pci设备。

但是,磁盘控制器不仅仅是一个pci设备,他的主要功能是控制磁盘驱动器,给磁盘驱动器下达命令来实现磁盘读写。为什么要这么设计呢?显然是为了解耦,使得硬盘和其他计算机组件能够独立发展。比如,在PCI在之前,我们用的是低速的ISA总线来连接IDE硬盘, 而现在ISA总线被PCI总线替代,还需要使用IDE硬盘,并且希望原来生产的IDE硬盘能够不做任何修改就能用到新的计算机系统里。

这个其实并不复杂,新的总线出来之后,为了把以前的IO设备连接到新的总线上,必须提供一个“总线适配器”,或者叫接口,这个接口一方面可以和总线做数据交互,另一方面需要知道怎么控制IO设备。这样才能将cpu的指令转换到对IO设备的指令。我们的磁盘控制器就是这样一个接口。它知道磁盘设备的指令集,所以获取cpu指令后,能翻译成磁盘设备的控制指令。事实上,传统的很多io设备都由一个控制器集成了南桥上,帮助io设备可以和局部总线交互数据。这也是南桥的价值所在。

所以,我们知道为什么同一个磁盘既能连在ISA总线的电脑上,也能连在PCI总线的电脑上,而磁盘的对外接口既不是ISA设备接口,也不是PCI设备接口,就是因为他们用了不同的磁盘驱动器。而使得磁盘设备可以独立发展其接口技术,不绑死在一条总线上。这更利于产业的有序发展。最后我们再回顾一下磁盘读写技术。我们如果想访问磁盘,必须找到磁盘驱动器,对其的io空间进行编址(这可能还有疑惑,以后讲到IO统一内存编址的时候就清楚了),然后根据磁盘控制器的使用说明,对其传达磁盘读写命令,最后获取结果。

而幸好以前的IDE磁盘控制器,有固定的IO空间,也就是在《cpu解读三:程序控制读写硬盘的方法》讲到的0x1F0 — 0x1F7 IDE等。在那篇文章中我们详细讲了应该怎样将读写磁盘的命令写入磁盘控制器的这些io寄存器里,来获取磁盘数据。

但是,如果每次读写磁盘都要往这些寄存器里写东西对程序员也太不友好了,于是程序员对这些操作进行了封装,以驱动的形式提供,甚至以更高级的api的形式供程序员调用,这就属于软件技术的范畴了,只不过无论软件程序怎么写,每一次磁盘读写的工作,必然是cpu指令对磁盘控制器的控制,再由磁盘控制器控制磁盘,这是最后的必经之路。