将设备作为文件
在
UNIX 中,几乎将所有东西都作为文件对待。UNIX 用户应用程序访问设备就像访问文件一样。代表设备的文件称为特殊文件或设备节点。设备特殊文件分为两类:块设备和字符设备。请参阅
Character and Block Devices 了解更多信息。
每个 I/O 服务开始都请求引用一个指定的文件。大多数读写数据的
I/O 操作,对普通或者特殊文件的执行都同样出色。例如,从文本编辑器创建的文件读取字节和从终端设备读取字节,都使用同一个
read(2)
系统调用。
控制信号也作为文件处理。使用
ioctl(9E)
函数操纵控制信号。
设备目录
Solaris OS 包含了 /dev
和 /devices 两个目录用于设备驱动程序。/dev 目录中的绝大多数驱动程序都是到
/devices 目录的链接。/dev 目录是 UNIX 的标准配置。/devices
目录专门针对 Solaris OS 存在。
根据约定,/dev
目录中的文件名称很容易读懂。例如,/dev 目录可能包含如 kdb 和 mouse
名称的文件,它们是到 /devices/pseudo/conskbd@0:kbd 文件和 /devices/pseudo/consms@0:mouse
文件的链接。prtconf(1M)
命令显示了与 /devices 目录中文件名称非常相似的设备名称。在下面的例子中,只显示了选定的命令输出。
% prtconf -P
conskbd, instance #0
consms, instance #0 |
/dev 目录中没有链接到 /devices 目录的入口是通过 mknod(1M)
或 mknod(2) 创建的设备节点或特殊文件。它们是长度为
0 的文件,只包含一个主设备编号和次设备编号。指向 /devices 目录中设备的物理名称链接要优于使用
mknod(1M)。
Solaris 10 OS 以前,/devices
是由子目录和文件组成的磁盘文件系统。在 Solaris 10 OS 中,/devices 是一个虚拟文件系统,按照需求创建了这些子目录和特殊文件。
了解更多关于设备文件系统的信息,请参阅 devfs(7FS)
手册页。
设备树
/devices
目录中的设备文件也称为设备树。
设备树展示了设备间的相互关系。在设备树中,目录代表一个节点设备。节点设备是可以作为其他设备父节点的设备。在下面的例子中,pci@1f,0
是一个节点设备。下面只显示了选定的命令输出。
# ls -l /devices
drwxr-xr-x 4 root sys 512 date time pci@1f,0/
crw------- 1 root sys 111,255 date time pci@1f,0:devctl |
您可以使用 prtconf(1M)
或 prtpicl(1M)
查看设备树的图示。请参阅 Writing
Device Drivers 一书的 Overview of the Device Tree 了解关于设备树的更多信息。
字符设备和块设备
设备树中的一个文件(不是目录)代表一个字符设备或一个块设备。
块设备可以包含可寻址和可复用数据。块设备的一个例子是文件系统。任何设备都可以是字符设备。大多数块设备也有字符接口。磁盘具有块和字符两个接口。在
/devices/pseudo 目录中,您可能会发现如下设备:
brw-r----- 1 root sys 85, 0 Nov 3 09:43 md@0:0,0,blk
crw-r----- 1 root sys 85, 0 Nov 3 09:43 md@0:0,0,raw
brw-r----- 1 root sys 85, 1 Nov 3 09:43 md@0:0,1,blk
crw-r----- 1 root sys 85, 1 Nov 3 09:43 md@0:0,1,raw
brw-r----- 1 root sys 85, 2 Nov 3 09:43 md@0:0,2,blk
crw-r----- 1 root sys 85, 2 Nov 3 09:43 md@0:0,2,raw 块设备在它们的文件模式中使用一个 b 作为第一个字符。字符设备在它们的文件模式中使用一个
c 作为第一个字符。在本例中,块设备名称中有 blk,字符设备名称中有 raw。
md(7D) 设备是提供磁盘服务的元设备。块设备使用系统的普通缓冲机制访问磁盘。字符设备提供磁盘和用户读写缓冲区间的直接传输。
设备名称
本节展示了一个复杂的设备名称并解释了 /dev 和 /devices
中名称的每一个部分的意义。下面的例子是磁盘分区的名称:
/dev/dsk/c0t0d0s7 -> ../../devices/pci@1c,600000/scsi@2/sd@0,0:h |
首先,检查 /dev 目录中的文件名称。这些名称由 devfsadmd(1M)
守护进程来管理。
- c0
-
控制器 0
- t0
-
目标 0。对于 SCSI 控制器,该值是磁盘的编号。
- d0
-
SCSI LUN。该值指明这是一个目标或单独物理设备的虚拟分区。
- s7
-
目标 0 磁盘上的 7 号分区。
对于相同的设备,可以比较 /devices 目录中的文件名称。这些名称展示了物理结构和实际设备名称。注意,/devices
目录中设备名称的一些组成部分是子目录。
- pci@1c,600000
-
PCI 总线地址 1c,600000。这些地址只对父设备有意义。
- scsi@2
-
SCSI 控制器地址是位于 1c,600000 地址的PCI 总线上的地址
2。这个名称对应 /dev/dsk/c0t0d0s7 中的 c0。
- sd@0,0
-
SCSI 磁盘地址是位于 2 地址的 SCSI 控制器上的地址 0,0。这个名称对应
/dev/dsk/c0t0d0s7 中的 t0。sd
名称和驱动程序也可以应用到 IDE CD-ROM 设备。
- sd@0,0:h
-
SCSI 磁盘上的次设备节点 h,地址是 0,0。这个名称对应 /dev/dsk/c0t0d0s7
中的 s7。
设备编号
设备编号用来区别设备树中的特殊设备和次要设备。许多 DDI/DKI例程需要的 dev_t
参数就是这个设备编号。
每个设备有一个主设备编号和一个次设备编号。设备编号由一对主设备编号/次设备编号组成。列出的长文件在位于通常列出文件大小的一列中展示了设备编号。在下面的例子中,设备编号是
86,255。设备主编号是 86,设备次编号是 255。
% ls -l /devices/pci@0,0:devctl
crw------- 1 root sys 86,255 date time /devices/pci@0,0:devctl |
在 Solaris OS 中,主设备编号在您安装驱动程序时被选定,这样就不会与其他主设备编号冲突。内核使用主设备编号将
I/O 请求与正确地驱动程序代码关联起来。然后内核使用这种关联,在用户读写设备文件时,决定执行那个驱动程序。所有设备和它们的主设备编号都罗列在
/etc/name_to_major 文件中。
% grep 86 /etc/name_to_major
pci 86 |
次设备编号在驱动程序中分配。次设备编号必须将每个设备驱动程序映射到一个具体的设备实例。次设备编号通常指子设备。例如,磁盘驱动程序可以与具有多个磁盘驱动器的硬件控制器设备通信。次设备节点没有必要使用物理表示。
下面的例子展示了 md 设备的实例 0、1 和 2。数字 0、1 和 2 是次设备编号。
brw-r----- 1 root sys 85, 0 Nov 3 09:43 md@0:0,0,blk
crw-r----- 1 root sys 85, 0 Nov 3 09:43 md@0:0,0,raw
brw-r----- 1 root sys 85, 1 Nov 3 09:43 md@0:0,1,blk
crw-r----- 1 root sys 85, 1 Nov 3 09:43 md@0:0,1,raw
brw-r----- 1 root sys 85, 2 Nov 3 09:43 md@0:0,2,blk
crw-r----- 1 root sys 85, 2 Nov 3 09:43 md@0:0,2,raw 在 sd@0,0:h 名称中,h
代表次设备节点。当驱动程序接收到一个次设备节点 h 的请求时,驱动程序实际接收的是对应的次设备编号。sd
节点的驱动程序将这个次设备编号解释为磁盘的一个具体部分,例如挂载在 /export 的分区 7。
第 2 章,模板驱动程序例子展示了如何在驱动程序中使用 ddi_get_instance(9F)
例程来获得正在使用的设备实例编号。
|