设备文件是用来表示Linux所支持的大多数设备的,每个设备文件除了设备名,还有三个属性:即类型、主设备号、次设备号。
设备文件是通过mknod系统调用创建的。其原型为:
mknod(const
char * filename, int mode, dev_t dev)
其参数有设备文件名、操作模式、主设备号及次设备号。最后两个参数合并成一个16位的dev_t无符号短整数,高8位用于主设备号,低8位用于次设备号。内核中定义了三个宏来处理主、次设备号:MAJOR和MINOR宏可以从16位数中提取出主、次设备号,而MKDEV宏可以把主、此号合并为一个16位数。实际上,dev_t是专用于应用程序的一个数据类型;在内核中使用kdev_t数据类型。在Linux 2.4及以前的版本中,这两个类型都会是一个无符号短整型,但是在以后的Linux版本中,kdev_t会成为一个完整的设备文件描述符,也就说,也许会扩成32位的长整数。
分配给设备号的正式注册信息及/dev目录索引节点存放在Documentation/devices.txt文件中。也可以在include/linux/major.h
文件中找到所支持的主设备号。
设备文件通常位于/dev目录下。表11.1显示了一些设备文件的属性。注意同一主设备号既可以标识字符设备,也可以标识块设备。
表11.1 设备文件的例子
设备名 |
类型 |
主设备号 |
次号 |
说明 |
/dev/fd0 |
块设备 |
2 |
0 |
软盘 |
/dev/hda |
块设备 |
3 |
0 |
第一个IDE磁盘 |
/dev/hda2 |
块设备 |
3 |
2 |
第一个IDE磁盘上的第二个主分区 |
/dev/hdb |
块设备 |
3 |
64 |
第二个IDE磁盘 |
/dev/hdb3 |
块设备 |
3 |
67 |
第二个IDE磁盘上的第三个主分区 |
/dev/ttyp0 |
字符设备 |
3 |
0 |
终端 |
/dev/console |
字符设备 |
5 |
1 |
控制台 |
/dev/lp1 |
字符设备 |
6 |
1 |
并口打印机 |
/dev/ttyS0 |
字符设备 |
4 |
64 |
第一个串口 |
/dev/rtc |
字符设备 |
10 |
135 |
实时时钟 |
/dev/null |
字符设备 |
1 |
3 |
空设备(黑洞) |
一个设备文件通常与一个硬件设备(如硬盘,/dev/hda)相关连, 或硬件设备的某一物理或逻辑分区(如磁盘分区,/dev/hda2)相关联。但在某些情况下,设备文件不会和任何实际的硬件关联,而是表示一个虚拟的逻辑设备。例如,/dev/null就是对应于一个“黑洞”的设备文件:所有写入这个文件的数据都被简单地丢弃,因此,该文件看起来总为空。
就内核所关心的内容而言,设备文件名是无关紧要的。如果你建立了一个名为/tmp/disk的设备文件,类型为“块”,主设备号是3,次设备号为0,那么这个设备文件就和表中的/dev/hda等价。另一方面,对某些应用程序来说,设备文件名可能就很有意义。例如,通信程序可以假设第一个串口和/dev/ttyS0设备文件关联。
1.块设备和字符设备的比较
块设备具有以下特点:
·
可以在一次I/O操作中传送固定大小的数据块。
·
可以随机访问设备中所存放的块:传送数据块所需要的时间独立于块在设备中的位置,也独立于当前设备的状态。
块设备典型的例子是硬盘、软盘及CD-ROM。也可以把RAM磁盘当作块设备来对待,这是通过把部分RAM配置成快速硬盘而获得的,因此,可以把这部分RAM作为应用程序高效存取数据的临时存储器。
字符设备具有以下特点:
·
可以在一次I/O操作中传送任意大小的数据。实际上,诸如打印机之类的字符设备可以一次传送一个字节,而诸如磁带之类的设备可以一次传送可变大小的数据块。
·
通常访问连续的字符。
2. 网卡
有些I/O设备没有对应的设备文件。最明显的一个例子是网卡。实际上,网卡把向外发送的数据放入通往远程计算机系统的一条线上,把从远程系统中接收到的报文装入内核内存。
从BSD开始,所有的Unix类系统为计算机中的每个网卡都分配一个不同的符号名;例如,第一个以太网卡名为eth0。然而,这个名字并没有对应的设备文件,也没有对应的索引节点。
由于没有使用文件系统,所以系统管理员必须建立设备名和网络地址之间的联系。因此,应用程序和网络接口之间的数据通信不是基于标准的有关文件的系统调用的;而是基于socket( )、bind( )、listen(
)、accept()和connect( )系统调用的,这些系统调用对网络地址进行操作。这组系统调用是在Unix BSD中首先引入的,现在已经成为网络设备的标准编程模型。