在本部分,将通过硬盘驱动程序直接操作硬盘。在编写这个文件系统的过程中,通过几个消息、用户进程、文件系统和驱动程序之间就可以方便的协同工作。
硬盘操作的I/O端口
和键盘控制器、VGA控制器等类似,对硬盘控制器的操作仍然是通过I/O端口来进行,这些端口分为两组,它们对应命令块寄存器和控制块寄存器,如下表:
对硬盘的操作并不复杂,只需要往命令块寄存器写入正确的值,再通过控制块寄存器发送命令就可以了。
硬盘驱动程序
驱动程序的作用在于隐藏硬件细节,向上层提供统一的接口。由于进程通过收发消息来相互通信,那么驱动程序的接口自然也是消息了。所以只要定义了驱动程序可以接受的消息,也就定义了驱动程序的接口。首先想硬盘驱动器发送一个IDENTIFY命令,这个命令可用来获取硬盘参数。
下面是Device寄存器的格式:
可以看到寄存器主要有LBA模式位、DRV位和低四位。DRV用于指定主盘或从盘,0表示主盘,1表示从盘。LBA模式位用于指定操作模式,当此位为0时,对磁盘的操作使用CHS模式;当为1时,对磁盘使用LBA模式。
我们使用函数hd_cmd_out()来进行实际的向硬件驱动器发送命令的工作,因为今后我们还会用到它。当发送命令之后,我们用interrupt_wait()来等待中断的发生。
驱动程序获知中断发生的情形如下:
建立如下文件系统进程:
1 | PUBLIC void task_fs() |
文件系统
我们结合前面学习的FAT12来了解文件系统,从下图可知,文件系统有4个部分:
- 引导扇区:存放Metadata—占用整整一个扇区的superblock
- FAT表:记录扇区使用情况—sector map
- 根目录区:文件的索引—inode map
- 数据区:记录任一文件的信息—root数据区
superblock通常也叫超级块,关于文件系统的Metadata都记录在这里。sector map是哟个位图,用来映射扇区的使用情况,用1表示扇区已经被使用。i-node是UNIX各种文件系统的核心数据结构之一。
硬盘分区表
硬盘分区表是一个结构体数组,数组的每个成员是一个16字节的结构体,如下:
我们将80MB的硬盘映像分成了一个主分区和一个扩展分区,扩展分区中又分成了5个逻辑分区。我们以后把写的操作系统放在第一个逻辑分区。先把它的分区类型(Systen ID)改成99h,又维他设定了“可启动”标志。
设备号
下图是所有分区:
其中数字1~4为主引导扇区中的分区表项所示,从5开始依次表示逻辑分区。
这些数字其实就是设备号,其作用是给每个设备起一个名字,这样驱动程序就能方便地管理他们。
对硬盘而言,采用如下的编号规则:
下面是遍历所有分区的情况:
完善硬盘驱动程序
目前的驱动程序只能处理DEV_OPEN消息,这显然是不够的,起码也要有DEV_READ和DEV_WRITE。下面先添加读写硬盘的功能:
1 | /***************************************************************************** |