设备文件对于每种硬件设备,系统内核有相应的设备驱动程序负责对它的处理。而在Unix中,使用设备文件的方式来表示硬件设备,每种设备驱动程序都被抽象为设备文件的形式,这样就给应用程序一个一致的文件界面,方便应用程序和操作系统之间的通信。所有的设备文件都放置在/dev目录下。
$ ls -l /dev/rfd0 /dev/fd0
brw-r----- 9 root operator 2, 0 Nov 12 13:32 /dev/fd0
crw-r----- 9 root operator 9, 0 Nov 12 13:32 /dev/rfd0
在上面的列表中可以看到原来显示文件大小的地方,现在改为显示两个用逗号分隔的数字。这是系统用来表示设备的两个重要的序号,第一个为主设备号(major number),用来表示设备使用的硬件驱动程序在系统中的序号;第二个为从设备号(minor number),硬件驱动程序使用它来区分不同的设备和判断如何进行处理。FreeBSD下主设备号用8位表示,而从设备号用24位来表示。事实上设备文件的名字并不重要,重要的是这两个设备号,操作系统使用它确定硬件驱动程序,并与硬件驱动程序进行通信。
磁盘和块设备文件
在Unix下将设备分为两种,块设备和字符设备,其中块设备主要用于随机存取的目的,磁盘为这一类设备的代表,而字符设备用于顺序存取的目的,例如磁带或终端设备。
磁盘设备的命名方式在前一章中提到过,磁盘设备由磁盘名、磁盘的序号、分区的序号、以及FreeBSD子分区的序号来表示,例如在设备wd0s1a中,wd为驱动程序,此后为设备序号,0表示为这个驱动程序的第一个设备,Unix习惯上从0开始计数,第三部分的分区序号为s1,注意这里为第一个分区,因为s1是从1开始向下排列的,与一般Unix的习惯不同,这是因为分区的概念是一个DOS概念,因此这里也使用与DOS相对应的顺序,最后一个a为FreeBSD子分区的顺序,每个UFS基本分区可以有8个子分区,这8个分区按照习惯用于不同的目的,例如wd0s1a用于根文件系统,wd0s1b用做交换分区,使用wd0s1c表示整个硬盘分区wd0s1。因此可以将fd0c用于对整个软盘fd0进行存取,wcd0c用于对整个光盘wcd0进行存取等。
传统名字,例如wd0a,可以用于表示第一个UFS分区上的a子分区,如wd0s1a。一般一个硬盘上只有一个UFS分区,因此可以直接使用传统名字标识磁盘分区。
在使用ls命令列表时,系统使用c(character)标识一个字符设备文件,使用b(block)标识块设备文件。
$ ls -l /dev/*wd0s1
crw-r----- 1 root operator 3, 131072 Oct 31 19:59 /dev/rwd0s1
brw-r----- 1 root operator 0, 131072 Oct 31 19:59 /dev/wd0s1
虽然硬盘设备为块设备,用于随机存取的目的。但它也可以被顺序存取,这种方式称为raw方式。使用raw方式存取硬盘,就需要一个对应的字符类型的设备文件,对应wd0s1硬盘设备的字符类型硬盘设备为rwd0s1,设备名中第一个字母使用r表示对硬盘的raw方式顺序存取。
由于设备文件就代表了整个设备,就可以使用FreeBSD的标准命令以raw方式直接操作设备文件,从而直接访问硬件设备。利用这种方式,能完成很多有用的工作,但是这种方式也非常危险,例如对硬盘设备文件的操作失误会破坏整个硬盘的数据。幸好大部分直接访问设备的操作都为读取相应数据的操作,而不需要写入磁盘设备。
当某个设备不可使用,则其对应的设备文件也不能正常访问,因此直接访问设备文件可以判断对应的设备是否真正正常。例如,判断连接到第一个串口,ttyd0上的鼠标是否正常工作,使用命令 “cat </dev/ttyd0” 来查看ttyd0上的输入数据,如果连接的有鼠标且工作正常,那么在移动鼠标的同时屏幕上就会显示出接收到的杂乱数据。如果没有反应,说明鼠标工作不正确。但这也可能是其他程序接管了这个设备,例如系统运行了moused。如果moused控制了鼠标端口,那么 “cat < /dev/sysmouse” 会给出答案。
cat或其他命令,没有控制具体接收到数据的多少,更有效的系统工具是dd,它能精确输入输出一定数量的数据。例如:# dd if=/dev/rwd0 of=mbr count=1 bs=512
这将以512字节为单位,读取硬盘wd0上一个单位的数据,保存到名字为mbr的文件中,通常这是硬盘wd0上的主引导扇区。
终端设备
终端设备文件为标识用户与系统连接的终端设备的设备文件,这是一种典型的字符设备文件。普通的终端一般使用串口和主机相连接,系统使用终端文件来描述这个连接的终端。通常第一个串口连接的设备为ttyd0(标准个人计算机第一个串口连接的常常是鼠标),第二个串口为ttyd1,依次类推。
如果用户是使用telnet或其他远程登录的方式,那么系统使用一个伪设备文件与用户的伪终端相对应,这些伪终端设备文件为ttyp0到ttysv,ttyP0到ttySv。这样就能支持相当多用户同时登录系统。
Unix是多用户、多任务系统,但是个人计算机仅仅有一个屏幕,熟练Unix用户喜欢同时进行几个工作,例如在一边下载文件,一边进行编程等,对于直接使用控制台的FreeBSD用户来讲,FreeBSD提供的虚拟终端能完美的解决这个问题。
对于在控制台上的虚拟终端,对应的终端设备文件为ttyv0、ttyv1、ttyv3等,与键盘上的12个功能键相对应。控制台设备被系统用来输出很多必要的信息,包括各种登录信息等对系统安全非常相关的信息。由于在控制台上操作就是在个人计算机前面操作,因此通常在控制台上能完成许多在其他终端上不能完成的操作,例如:使用Ctrl+Alt+Del重起系统等。为了保证系统安全,必须限制对控制台的物理访问。
对于不在控制台的用户,就需要额外的应用程序的支持,在X终端上能使用X Window系统开出多个窗口,每个窗口对应一个伪终端。在字符终端上,也可以通过应用程序screen打开几个伪终端,但这需要安装相应的软件。这些伪终端都使用ttyp0等伪设备文件。
与终端相关的另一个问题为不同的终端设备分为不同的终端类型,这是因为虽然终端是字符型设备,但又要求它能够具备更复杂的功能,例如进行全屏幕操作等。这样就要求终端设备能接受和识别一些控制字符,而不同的终端设备具备不同的控制字符。登录用户可以使用TERM环境变量来告诉应用程序当前使用的终端类型,常用的终端类型有vt100,ansi等,FreeBSD控制台的终端类型为cons25,但是其他Unix中一般不识别这个类型,因此如果在FreeBSD上通过telnet等连接到其他Unix上之后,应该改变TERM变量的值为ansi。
在FreeBSD中,终端类别对应的控制字符使用termcap的方法定义,而System V中使用terminfo的方式。所有的终端类型记录在/usr/share/misc/termcap文件中,并定义这些终端对应的控制字符。
登录到系统之后,将有一个终端设备文件与用户的这个登录过程相联系。这个终端设备文件在控制台上登录时可能是/dev/ttyv0,如果从网络上远程登录可能是/dev/ttyp0,但无论是那种情况,系统总使用/dev/tty来代表用户当前使用的终端,直接访问/dev/tty将对当前的终端进行直接操作。
除了这些与设备相联系的设备文件之外,还有一些特殊的设备文件。例如/dev/zero文件代表一个永远输出0的设备文件,使用它作输入可以得到全为空的文件。因此可用来创建新文件和以覆盖的方式清除旧文件。下面使用dd命令将从zero设备中创建一个10K大小(bs决定每次读写1024字节,count定义读写次数为10次),但内容全为0的文件。
# dd if=/dev/zero of=file count=10 bs=1024
10+0 records in
10+0 records out
10240 bytes transferred in 0.001408 secs (7267903 bytes/sec)
另一个特殊设备文件为/dev/null,永远无法写满,写入的内容被系统立即丢弃。如果不想看到程序的输出,可以使用它作输出。
# make world > /dev/null
去除了屏幕输出,使整个程序执行过程非常平静。
设备文件的创建
通常情况下,安装系统时已经创建了常用的设备文件,可以直接访问这些设备文件来访问设备。但在用户重新定制内核,并添加了新硬件驱动程序之后,新驱动程序对应的设备文件就可能不存在。在FreeBSD中,最常见的例子就是在内核中增加声卡的驱动程序时,就需要创建相应设备文件。
创建设备文件可以使用/dev目录下的shell程序MAKEDEV来完成,首先进入/dev目录,然后再执行MAKEDEV。
# cd /dev
# ./MAKEDEV snd0
MAKEDEV将使用设备名作参数创建设备文件,同时也创建这个设备文件依赖的其他相关设备文件。MAKEDEV的参数,并不一定为创建的设备文件名。例如建立 “MAKEDEV vty8” 将建立ttyv0到ttyv7共8个设备文件,使用 “MAKEDEV wd1s1a” 命令,将建立wd1、wd1s1、wd1s2等,以及wd1s1a、wd1s1b等设备文件。也可以使用all做MAKEDEV的参数,这将首先清除/dev目录下的所有设备文件,然后MAKEDEV创建所有预设的设备文件。一般情况下这将创建足够多的设备文件,其中的大部分设备文件在具体的系统中不会用得到。
如果对一个系统中没有(或者内核没有探测到)的设备对应的设备文件进行操作,则系统返回Device not configured的错误信息。
MAKEDEV将使用mknod和对应设备的正确参数,包括字符或块设备、主设备号和从设备号来建立相应的设备文件。管理员也可以直接使用mknod创建设备文件,但这就必须将这些设备参数统统指定正确才行。因此除非对系统中的硬件驱动程序特别熟悉,一般不直接使用mknod来创建设备文件。
未完,待续。。。