在初始化的时候 Linux 映射系统中的硬盘的拓扑结构。它找出系统中有多少个硬盘以及硬盘的类型。 Linux 还找出每一个磁盘如何分区。这些都是由 gendisk_head 指针列表指向的一组 gendisk 数据结构的列表表达。对于每一个磁盘子系统,例如 IDE ,初始化的时候生成 gendisk 数据结构表示它找到的磁盘。这个过程和它登记它的文件操作和在 blk_dev 数据结构中增加它的条目发生在同一时间。每一个 gendisk 数据结构都由一个唯一的主设备号,和块特殊设备的相同。例如, SCSI 磁盘子系统会创建一个独立的 gendisk 条目(“ sd ”),主设备号是 8 (所有 SCSI 磁盘设备的主设备号)。图 8.3 显示了两个 gendisk 条目,第一个是 SCSI 磁盘子系统,第二个是 IDE 磁盘控制器。这里是 ide0 ,主 IDE 控制器。
虽然磁盘子系统在初始化的时候会建立相应的 gendisk 条目, Linux 只是在进行分区检查的时候才用到。每一个磁盘子系统必须维护自己的数据结构,让它自己可以把设备的主设备号和次设备号映射到物理磁盘的分区上。不管什么时候读写块设备,不管是通过 buffer cache 或者文件操作,核心都根据它在块特殊设备文件(例如 /dev/sda2 )中找到的主设备号和次设备号把操作定向到合适的设备。是每一个设备驱动程序或子系统把次设备号映射到真正的物理设备上。
8.5.1 IDE Disks ( IDE 磁盘)
今天 Linux 系统中最常用的磁盘是 IDE 磁盘( Integrated Disk Electronic )。 IDE 和 SCSI 一样是一个磁盘接口而不是一个 I/O 总线。每一个 IDE 控制器可以支持最多 2 个磁盘,一个是 master ,另一个是 slave 。 Master 和 slave 通常用磁盘上的跳线设置。系统中的第一个 IDE 控制器叫做主 IDE 控制器,下一个叫从属控制器等等。 IDE 可以从 / 向磁盘进行 3.3M/ 秒的传输, IDE 磁盘的最大尺寸是 538M 字节。扩展 IDE 或 EIDE 把最大磁盘尺寸增加到 8.6G 字节,数据传输速率高达 16.6M/ 秒。 IDE 和 EIDE 磁盘比 SCSI 磁盘便宜,大多数现代 PC 都有一个或更多的主板上的 IDE 控制器。
Linux 按照它发现的控制器的顺序命名 IDE 磁盘。主控制器上的主磁盘是 /dev/had , slave 磁盘是 /dev/hdb 。 /dev/hdc 是次 IDE 控制器上的 master 磁盘。 IDE 子系统向 Linux 登记 IDE 控制器而不是磁盘。主 IDE 控制器的主标识符是 3 ,次 IDE 控制器的标识符是 22 。这意味着如果一个系统有两个 IDE 控制器,那么在 blk_dev 和 blkdevs 向量表中在索引 3 和 22 会有 IDE 子系统的条目。 IDE 磁盘的块特殊文件反映了这种编号:磁盘 /dev/had 和 /dev/hdb ,都连接在主 IDE 控制器上,主设备号都是 3 。核心使用主设备标识符作为索引,对于这些块特殊文件的 IDE 子系统进行的所有的文件或者 buffer cache 操作都被定向到相应的 IDE 子系统。当执行一个请求的时候, IDE 子系统负责判断这个请求是针对哪一个 IDE 磁盘。为此, IDE 子系统使用设备特殊文件中的次设备号,这些信息允许它把请求定向到正确的磁盘的正确的分区。 /dev/hdb ,主 IDE 控制器上的 slave IDE 磁盘的设备标识符是( 3 , 64 )。它的第一个分区( /dev/hdb1 )的设备标识符是( 3 , 65 )。
8.5.2 Initializing the IDE Subsystem (初始化 IDE 子系统)
IBM PC 的大部分历史中都有 IDE 磁盘。这期间这些设备的接口发生了变化。这让 IDE 子系统的初始化过程比它第一次出现的时候更加复杂。
Linux 可以支持的最大 IDE 控制器数目是 4 。每一个控制器都用一个 ide_hwifs 向量表中的一个 ide_hwif_t 数据结构表示。每一个 ide_hwif_t 数据结构包含两个 ide_drive_t 数据结构,分别表示可能支持的 master 和 slave IDE 驱动器。在 IDE 子系统初始化期间, Linux 首先查看在系统的 CMOS 内存中记录的磁盘的信息。这种用电池做后备的内存在 PC 关机的时候不会丢失它的内容。这个 CMOS 内存实际上在系统的实时时钟设备里面,不管你的 PC 开或者关,它都在运行。 CMOS 内存的位置由系统的 BIOS 设置,同时告诉 Linux 系统中找到了什么 IDE 控制器和驱动器。 Linux 从 BIOS 中获取找到的磁盘的尺寸( geometry ),用这些信息设置这个驱动器的 ide_hwif_t 的数据结构。大多数现代 PC 使用 PCI 芯片组例如 Intel 的 82430 VX 芯片组,包括了一个 PCI EIDE 控制器。 IDE 子系统使用 PCI BIOS 回调( callback )定位系统中的 PCI ( E ) IDE 控制器。然后调用这些芯片组的询问例程。
一旦发现一个 IDE 接口或者控制器,就设置它的 ide_hwif_t 来反映这个控制器和上面的磁盘。操作过程中 IDE 驱动程序向 I/O 内存空间的 IDE 命令寄存器写命令。主 IDE 控制器的控制和状态寄存器的缺省的 I/O 地址是 0x1F0-0x1F7 。这些地址是早期的 IBM PC 约定下来的。 IDE 驱动程序向 Linux 的 buffer cache 和 VFS 登记每一个控制器,分别把它加到 blk_dev 和 blkdevs 向量表中。 IDE 驱动程序也请求控制适当的中断。同样,这些中断也有约定,主 IDE 控制器是 14 ,次 IDE 控制器是 15 。但是,象所有的 IDE 细节一样,这些都可以用核心的命令行选项改变。 IDE 驱动程序在启动的时候也为每一个找到的 IDE 控制器在 gendisk 列表中增加一个 gendisk 条目。这个列表稍后用于查看启动时找到的所有的硬盘的分区表。分区检查代码明白每一个 IDE 控制器可以控制两个 IDE 磁盘。