📄 00000009.htm
字号:
IDE的块设备文件反应了这种编号方式,硬盘/dev/hda和/dev/hdb都连接 <BR>到主IDE控制器上,其主标志符为3。对IDE子系统上这些块相关文件的文 <BR>件或者buffercache的操作都通过核心使用主设备标志符作为索引定向到 <BR>IDE子系统上。当发出请求时,此请求由哪个IDE硬盘来完成取决于IDE子 <BR>系统。为了作到这一点IDE子系统使用从设备编号对应的设备特殊标志符, <BR>由它包含的信息来将请求发送到正确的硬盘上。位于主IDE控制器上的IDE <BR>从盘/dev/hdb的设备标志符为(3,64)。而此盘中第一个分区(/dev/hdb1) <BR>的设备标志符为(3,65)。 <BR>8.5.2 初始化IDE子系统 <BR>IDE磁盘与IBM <BR>PC关系非常密切。在这么多年中这些设备的接口发生了变化。这使得IDE <BR>子系统的初始化过程比看上去要复杂得多。 <BR>Linux可以支持的最多IDE控制器个数为4。每个控制器用ide_hwifs数组 <BR>中的ide_hwif_t结构来表示。每个ide_hwif_t结构包含两个ide_drive_t <BR>结构以支持主从IDE驱动器。在IDE子系统的初始化过程中Linux通过访问 <BR>系统CMOS来判断是否有关于硬盘的信息。这种CMOS由电池供电所以系统断 <BR>电时也不会遗失其中的内容。它位于永不停止的系统实时时钟设备中。 <BR>此CMOS内存的位置由系统BIOS来设置,它将通知Linux系统中有多少个IDE <BR>控制器与驱动器。Linux使用这些从BIOS中发现的磁盘数据来建立对应此 <BR>驱动器的ide_hwif_t结构。 <BR>许多现代PC系统使用PCI芯片组如Intel 82430 VX芯片组将PCIEIDE控制器 <BR>封装在内。IDE子系统使用PCI BIOS回调函数来定位系统中PCI(E)IDE控 <BR>制器。然后对这些芯片组调用PCI特定查询例程。 <BR>每次找到一个IDE接口或控制器就有建立一个ide_hwif_t结构来表示控制 <BR>器和与之相连的硬盘。在操作过程中IDE驱动器对I/O内存空间中的IDE命 <BR>令寄存器写入命令。主IDE控制器的缺省控制和状态寄存器是0x1F0- 0x1F7。 <BR>这个地址由早期的IBM PC规范设定。IDE驱动器为每个控制器向Linux注 <BR>册块缓冲cache和VFS节点并将其加入到blk_dev和blkdevs数组中。IDE驱 <BR>动器需要申请某个中断。一般主IDE控制器中断号为14而从属IDE控制器为 <BR>15。然而这些都可以通过命令行选项由核心来重载。IDE驱动器同时还将 <BR>gendisk入口加入到启动时发现的每个IDE控制器的gendisk链表中去。分 <BR>区检查代码知道每个IDE控制器可能包含两个IDE硬盘。 <BR>8.5.3 SCSI 硬盘 <BR>SCSI(小型计算机系统接口)总线是一种高效的点对点数据总线,它最 <BR>多可以支持8个设备,其中包括多个主设备。每个设备有唯一的标志符并 <BR>可以通过盘上的跳线来设置。在总线上的两个设备间数据可以以同步或异 <BR>步方式,在32位数据宽度下传输率为40M字节来交换数据。SCSI总线上可 <BR>以在设备间同时传输数据与状态信息。initiator设备和target设备间的 <BR>执行步骤最多可以包括8个不同的阶段。你可以从总线上5个信号来分辨SCSI <BR>总线的当前阶段。这8个阶段是: <BR>BUS FREE <BR> 当前没有设备在控制总线且总线上无事务发生。 <BR>ARBITRATION <BR> 一个SCSI设备试图取得SCSI总线的控制权,这时它将其SCSI标志符 <BR> 放置到地址引脚上。具有最高SCSI标志符编号的设备将获得总线控制权。 <BR>SELECTION <BR> 当设备通过仲裁成功地取得了对SCSI总线的控制权后它必须向它准备 <BR> 发送命令的那个SCSI设备发出信号。具体做法是将目标设备的SCSI标志 <BR> 符放置在地址引脚上进行声明。 <BR>RESELECTION <BR> 在一个请求的处理过程中SCSI设备可能会断开连接。目标(target) <BR> 设备将再次选择启动设备(initiator)。不是所有的SCSI设备都支 <BR> 持此阶段。 <BR>COMMAND <BR> 此阶段中initiator设备将向target设备发送6、10或12字节命令。 <BR>DATA IN, DATA OUT <BR> 此阶段中数据将在initiator设备和target设备间传输。 <BR>STATUS <BR> 所有命令完毕后将进入此阶段,此时允许target设备向initiator <BR> 设备发送状态信息以指示操作成功与否。 <BR>MESSAGE IN, MESSAGE OUT <BR> 此阶段附加信息将在initiator设备和target设备间传输。 <BR>Linux SCSI子系统由两个基本部分组成,每个由一个数据结构来表示。 <BR>host 一个SCSI host即一个硬件设备:SCSI控制权。NCR 810 PCI <BR> SCSI控制权即一种SCSI host。在Linux <BR> 系统中可以存在相同类型的多个SCSI控制权,每个由一个单独的 <BR> SCSI host来表示。这意味着一个SCSI设备驱动可以控制多个控制 <BR> 权实例。SCSI host总是SCSI命令的initiator设备。 <BR>Device <BR> 虽然SCSI支持多种类型设备如磁带机、CD-ROM等等,但最常见的 <BR> SCSI设备是SCSI磁盘。SCSI设备总是SCSI命令的target。这些设备 <BR> 必须区别对待,例如象CD-ROM或者磁带机这种可移动设备,Linux <BR> 必须检测介质是否已经移动。不同的磁盘类型有不同的主设备号, <BR> 这样Linux可以将块设备请求发送到正确的SCSI设备。 <BR>初始化SCSI子系统 <BR>SCSI子系统的初始化非常复杂,它必须反映处SCSI总线及其设备的动态 <BR>性。Linux在启动时初始化SCSI子系统。 <BR>如果它找到一个SCSI控制器(即SCSI hosts)则会扫描此SCSI总线来找 <BR>出总线上的所有设备。然后初始化这些设备并通过普通文件和buffer <BR>cache块设备操作使Linux核心的其它部分能使用这些设备。初始化过程 <BR>分成四个阶段: <BR>首先Linux将找出在系统核心连接时被连入核心的哪种类型的SCSI主机适 <BR>配器或控制器有硬件需要控制。每个核心中的SCSI host在builtin_scsi_hosts <BR>数组中有一个Scsi_Host_Template入口。而Scsi_Host_Template结构中包 <BR>含执行特定SCSIhost操作, 如检测连到此SCSI host的SCSI设备的例程的入 <BR>口指针。这些例程在SCSI子系统进行自我配置时使用同时它们还是支持 <BR>此host类型的SCSI设备驱动的一部分。每个被检测的SCSI host,即与真 <BR>正SCSI设备连接的host将其自身的Scsi_Host_Template结构添加到活动 <BR>SCSIhosts的scsi_hosts结构链表中去。每个被检测host类型的实例用一 <BR>个scsi_hostlist链表中的Scsi_Host结构来表示。例如一个包含两个NCR810 <BR>PCI SCSI控制器的系统的链表中将有两个Scsi_Host入口,每个控制器对 <BR>应一个。每个Scsi_Host指向一个代表器设备驱动的Scsi_Host_Template。 <BR>现在每个SCSI host已经找到,SCSI子系统必须找出哪些SCSI设备连接哪 <BR>个host的总线。SCSI设备的编号是从0到7,对于一条SCSI总线上连接的各 <BR>个设备,其设备编号或SCSI标志符是唯一的。SCSI标志符可以通过设备上 <BR>的跳线来设置。SCSI初始化代码通过在SCSI总线上发送一个TEST_UNIT_READY <BR>命令来找出每个SCSI设备。当设备作出相应时其标志符通过一个ENQUIRY命 <BR>令来读取。Linux将从中得到生产厂商的名称和设备模式以及修订版本号。 <BR>SCSI命令由一个Scsi_Cmnd结构来表示同时这些命令通过调用Scsi_Host_Template <BR>结构中的设备驱动例程传递到此SCSIhost的设备驱动中。被找到的每个SCSI <BR>设备用一个Scsi_Device结构来表示,每个指向其父Scsi_Host结构。所有 <BR>这些Scsi_Device结构被添加到scsi_device链表中。图8.4给出了这些主要 <BR>数据结构间的关系。 <BR>一共有四种SCSI设备类型:磁盘,磁带机,CD-ROM和普通SCSI设备。每种类 <BR>型的SCSI设备以不同的主块设备类型单独登记到核心中。如果有多个类型的 <BR>SCSI设备存在则它们只登记自身。每个SCSI设备类型,如SCSI磁盘维护着其 <BR>自身的设备列表。它使用这些表将核心块操作(file或者buffer cache)定 <BR>向到正确的设备驱动或 SCSI host上。每种SCSI设备类型用一个 <BR>Scsi_Device_Template结构来表示。此结构中包含此类型SCSI设备的信息以 <BR>及执行各种任务的例程的入口地址。换句话说,如果SCSI子系统希望连接一 <BR>个SCSI磁盘设备它将调用SCSI磁盘类型连接例程。如果有多个该种类型的SCSI <BR>设备被检测到则此Scsi_Type_Template结构将被添加到scsi_devicelist链表中。 <BR>SCSI子系统的最后一个阶段是为每个已登记的Scsi_Device_Template结构调用 <BR>finish函数。对于SCSI磁盘类型设备它将驱动所有SCSI磁盘并记录其磁盘布局。 <BR>同时还将添加一个表示所有连接在一起的SCSI磁盘的gendisk结构。 <BR>发送块设备请求 <BR>一旦SCSI子系统初始化完成这些SCSI设备就可以使用了。每个活动的SCSI设备 <BR>类型将其自身登记到核心以便Linux正确定向块设备请求。这些请求可以是通 <BR>过blk_dev的buffercache请求也可以是通过blkdevs的文件操作。以一个包含 <BR>多个EXT2文件系统分区的SCSI磁盘驱动器为例,当安装其中一个EXT2分区时系 <BR>统是怎样将核心缓冲请求定向到正确的SCSI磁盘的呢? <BR>每个对SCSI磁盘分区的块读写请求将导致一个新的request结构被添加到对应 <BR>此SCSI磁盘的blk_dev数组中的current_request链表中。如果此request正在 <BR>被处理则buffercache无需作任何工作;否则它必须通知SCSI磁盘子系统去处 <BR>理它的请求队列。系统中每个SCSI磁盘用一个Scsi_Disk结构来表示。例如 <BR>/dev/sdb1的主设备号为8而从设备号为17;这样产生一个索引值1。每个 <BR>Scsi_Disk结构包含一个指向表示此设备的Scsi_Device结构。这样反过来又 <BR>指向拥有它的Scsi_Host结果。这个来自buffer cache的request结构将被转 <BR>换成一个描叙SCSI命令的Scsi_Cmd结构,这个SCSI命令将发送到此SCSI设备 <BR>同时被排入表示此设备的Scsi_Host结构。一旦有适当的数据块需要读写,这 <BR>些请求将被独立的SCSI设备驱动来处理。 <BR>8.6 网络设备 <BR>网络设备,即Linux的网络子系统,是一个发送与接收数据包的实体。它一般 <BR>是一个象以太网卡的物理设备。有些网络设备如loopback设备仅仅是一个用 <BR>来向自身发送数据的软件。每个网络设备都用一个device结构来表示。网络 <BR>设备驱动在核心启动初始化网络时将这些受控设备登记到Linux中。device数 <BR>据结构中包含有有关设备的信息以及用来支持各种网络协议的函数地址指针。 <BR>这些函数主要用来使用网络设备传输数据。设备使用标准网络支持机制来将接 <BR>收到的数据传递到适当的协议层。所有传输与接收到的网络数据用一个sk_buff <BR>结构来表示,这些灵活的数据结构使得网络协议头可以更容易的添加与删除。 <BR>网络协议层如何使用网络设备以及如何使用sk_buff来交换数据将在网络一章 <BR>中详细描叙。本章只讨论device数据结构及如何发现与初始化网络。 <BR>device数据结构包含以下有关网络设备的信息: <BR>Name <BR> 与使用mknod命令创建的块设备特殊文件与字符设备特殊文件不同,网络 <BR> 设备特殊文件仅在于系网络设备发现与初始化时建。它们使用标立 准的命名 <BR>方法 <BR> 每个名字代表一种类型的设备。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -