因为在保护模式下无法调用BIOS中断,所以只好自己编写代码控制硬盘读写。
对于硬件的控制,其实就是往对应的端口读写数据,硬盘也是如此。当硬盘控制器完成某项操作时,则会用中断的方法提示CPU。我们所要做的,就是先根据需要往端口读写数据,然后设置相应的中断调用函数。这样就可以完成硬盘的读写工作。
中断调用函数的内容主要是在硬盘控制器完成任务后做一些检查、善后的工作,但会根据不同的硬盘操作而有所不同。而硬盘控制器完成工作后都会触发同一中断。Linux中运用了很不错的思想,就是在硬盘中断中调用一个函数指针。在交给硬盘一项任务时,同时设置这个函数指针。这个任务所产生的中断就会调用对应的函数。这样我们就可以针对不同的任务写不同的中断函数了。
下面分析一下Linux0.11中的控制硬盘代码。
Linux中用块设备表blk_dev[NR_BLK_DEV]将块设备(struct blk_dev_struct)组织起来,每个块设备有两项内容,一个函数指针,只想块设备对应的操作函数。另一个是请求内容(struct request)指针。所有的请求结构都放在请求数组中(request[NR_REQUEST]),不区分设备。而请求设备相同的请求则穿在同一个链表中,由块设备的第二个指针指向对应的链表头。有新请求产生时,用电梯算法插入对应的链表。
硬盘的参数是从BIOS的参数表中读入的,Linux在实模式下将需要的BIOS参数放在一个固定位置,而在硬盘初始化时将它读出。
其他的大都非常简单明了,不用多做解释。
读硬盘分区表的那部分代码我还没有完全搞懂,这牵涉到了缓冲区结构的控制。
关于缓冲区的问题还有很多,比如在缓冲区上等待(sleep),唤醒进程,以及更新标志等等。
OS是个整体,许多内容都会相互牵连,只有慢慢抽丝拨茧,一层层学习。
当然不考虑硬盘分区表和缓冲区控制,我们还是可以写个很简单的硬盘控制驱动,希望多动手尝试一下。