1.5. /dev

/dev 是特殊文件或设备文件的位置。这是一个非常有趣的目录,突出了 Linux 文件系统的一个重要方面 - 一切皆文件或目录。浏览此目录,您应该会看到 hda1、hda2 等...,它们代表系统中第一个主驱动器上的各个分区。/dev/cdrom 和 /dev/fd0 代表您的 CD-ROM 驱动器和软盘驱动器。这可能看起来很奇怪,但如果您将文件的特性与硬件的特性进行比较,就会变得有意义。两者都可以读取和写入。以 /dev/dsp 为例。此文件代表您的扬声器设备。写入此文件的任何数据都将重定向到您的扬声器。如果您尝试 'cat /boot/vmlinuz > /dev/dsp'(在正确配置的系统上),您应该会在扬声器上听到一些声音。那是您的内核的声音!发送到 /dev/lp0 的文件会被打印出来。发送数据到 /dev/ttyS0 并从中读取数据将允许您与连接在那里的设备通信 - 例如,您的调制解调器。

大多数设备要么是块设备,要么是字符设备;然而,还存在其他类型的设备,并且可以创建。一般来说,“块设备”是存储或保存数据的设备,“字符设备”可以被认为是传输或传送数据的设备。例如,软盘驱动器、硬盘驱动器和 CD-ROM 驱动器都是块设备,而串行端口、鼠标和并行打印机端口都是字符设备。存在某种命名方案,但在绝大多数情况下,这些方案完全不合逻辑。

total 724
lrwxrwxrwx    1 root     root           13 Sep 28 18:06 MAKEDEV -> /sbin/MAKEDEV
crw-rw----    1 root     audio     14,  14 Oct  7 16:26 admmidi0
crw-rw----    1 root     audio     14,  30 Oct  7 16:26 admmidi1
lrwxrwxrwx    1 root     root           11 Oct  7 16:26 amidi -> /dev/amidi0
crw-rw----    1 root     audio     14,  13 Oct  7 16:26 amidi0
crw-rw----    1 root     audio     14,  29 Oct  7 16:26 amidi1
crw-rw----    1 root     audio     14,  11 Oct  7 16:26 amixer0
crw-rw----    1 root     audio     14,  27 Oct  7 16:26 amixer1
drwxr-xr-x    2 root     root         4096 Sep 28 18:05 ataraid
lrwxrwxrwx    1 root     root           11 Oct  7 16:26 audio -> /dev/audio0
crw-rw----    1 root     audio     14,   4 Oct  7 16:26 audio0
crw-rw----    1 root     audio     14,  20 Oct  7 16:26 audio1
crw-rw----    1 root     audio     14,   7 Mar 15  2002 audioctl
lrwxrwxrwx    1 root     root            9 Oct 14 22:51 cdrom -> /dev/scd1
lrwxrwxrwx    1 root     root            9 Oct 14 22:52 cdrom1 -> /dev/scd0
crw-------    1 root     tty        5,   1 Jan 19 20:47 console
lrwxrwxrwx    1 root     root           11 Sep 28 18:06 core -> /proc/kcore
crw-rw----    1 root     audio     14,  10 Oct  7 16:26 dmfm0
crw-rw----    1 root     audio     14,  26 Oct  7 16:26 dmfm1
crw-rw----    1 root     audio     14,   9 Oct  7 16:26 dmmidi0
crw-rw----    1 root     audio     14,  25 Oct  7 16:26 dmmidi1
lrwxrwxrwx    1 root     root            9 Oct  7 16:26 dsp -> /dev/dsp0
crw-rw----    1 root     audio     14,   3 Oct  7 16:26 dsp0
crw-rw----    1 root     audio     14,  19 Oct  7 16:26 dsp1
crw--w----    1 root     video     29,   0 Mar 15  2002 fb0
crw--w----    1 root     video     29,   1 Mar 15  2002 fb0autodetect
crw--w----    1 root     video     29,   0 Mar 15  2002 fb0current
crw--w----    1 root     video     29,  32 Mar 15  2002 fb1
crw--w----    1 root     video     29,  33 Mar 15  2002 fb1autodetect
crw--w----    1 root     video     29,  32 Mar 15  2002 fb1current
lrwxrwxrwx    1 root     root           13 Sep 28 18:05 fd -> /proc/self/fd
brw-rw----    1 root     floppy     2,   0 Mar 15  2002 fd0
brw-rw----    1 root     floppy     2,   1 Mar 15  2002 fd1
crw--w--w-    1 root     root       1,   7 Sep 28 18:06 full
brw-rw----    1 root     disk       3,   0 Mar 15  2002 hda
brw-rw----    1 root     disk       3,  64 Mar 15  2002 hdb
brw-rw----    1 root     disk      22,   0 Mar 15  2002 hdc
brw-rw----    1 root     disk      22,  64 Mar 15  2002 hdd
drwxr-xr-x    2 root     root        12288 Sep 28 18:05 ida
prw-------    1 root     root            0 Jan 19 20:46 initctl
brw-rw----    1 root     disk       1, 250 Mar 15  2002 initrd
drwxr-xr-x    2 root     root         4096 Sep 28 18:05 input
crw-rw----    1 root     dialout   45, 128 Mar 15  2002 ippp0
crw-rw----    1 root     dialout   45,   0 Mar 15  2002 isdn0
crw-rw----    1 root     dialout   45,  64 Mar 15  2002 isdnctrl0
crw-rw----    1 root     dialout   45, 255 Mar 15  2002 isdninfo
crw-------    1 root     root      10,   4 Mar 15  2002 jbm
crw-r-----    1 root     kmem       1,   2 Sep 28 18:06 kmem
brw-rw----    1 root     cdrom     24,   0 Mar 15  2002 lmscd
crw-------    1 root     root      10,   0 Mar 15  2002 logibm
brw-rw----    1 root     disk       7,   0 Sep 28 18:06 loop0
brw-rw----    1 root     disk       7,   1 Sep 28 18:06 loop1
crw-rw----    1 root     lp         6,   0 Mar 15  2002 lp0
crw-rw----    1 root     lp         6,   1 Mar 15  2002 lp1
crw-rw----    1 root     lp         6,   2 Mar 15  2002 lp2
crw-r-----    1 root     kmem       1,   1 Sep 28 18:06 mem
lrwxrwxrwx    1 root     root           10 Oct  7 16:26 midi -> /dev/midi0
crw-rw----    1 root     audio     14,   2 Oct  7 16:26 midi0
crw-rw----    1 root     audio     14,  18 Oct  7 16:26 midi1
lrwxrwxrwx    1 root     root           11 Oct  7 16:26 mixer -> /dev/mixer0
crw-rw-rw-    1 root     root      14,   0 Nov 11 16:22 mixer0
crw-rw----    1 root     audio     14,  16 Oct  7 16:26 mixer1
lrwxrwxrwx    1 root     root           11 Oct  7 06:50 modem -> /dev/ttyLT0
crw-rw----    1 root     audio     31,   0 Mar 15  2002 mpu401data
crw-rw----    1 root     audio     31,   1 Mar 15  2002 mpu401stat
crw-rw----    1 root     audio     14,   8 Oct  7 16:26 music
crw-rw-rw-    1 root     root       1,   3 Sep 28 18:06 null
crw-rw-rw-    1 root     root     195,   0 Jan  6 03:03 nvidia0
crw-rw-rw-    1 root     root     195,   1 Jan  6 03:03 nvidia1
crw-rw-rw-    1 root     root     195, 255 Jan  6 03:03 nvidiactl
crw-rw----    1 root     lp         6,   0 Mar 15  2002 par0
crw-rw----    1 root     lp         6,   1 Mar 15  2002 par1
crw-rw----    1 root     lp         6,   2 Mar 15  2002 par2
-rw-r--r--    1 root     root       665509 Oct  7 16:41 pcm
crw-r-----    1 root     kmem       1,   4 Sep 28 18:06 port
crw-rw----    1 root     dip      108,   0 Sep 28 18:07 ppp
crw-------    1 root     root      10,   1 Mar 15  2002 psaux
crw-rw-rw-    1 root     root       1,   8 Sep 28 18:06 random
crw-rw----    1 root     root      10, 135 Mar 15  2002 rtc
brw-rw----    1 root     cdrom     11,   0 Mar 15  2002 scd0
brw-rw----    1 root     cdrom     11,   1 Mar 15  2002 scd1
brw-rw----    1 root     disk       8,   0 Mar 15  2002 sda
brw-rw----    1 root     disk       8,   1 Mar 15  2002 sda1
brw-rw----    1 root     disk       8,   2 Mar 15  2002 sda2
brw-rw----    1 root     disk       8,   3 Mar 15  2002 sda3
brw-rw----    1 root     disk       8,   4 Mar 15  2002 sda4
brw-rw----    1 root     disk       8,  16 Mar 15  2002 sdb
brw-rw----    1 root     disk       8,  17 Mar 15  2002 sdb1
brw-rw----    1 root     disk       8,  18 Mar 15  2002 sdb2
brw-rw----    1 root     disk       8,  19 Mar 15  2002 sdb3
brw-rw----    1 root     disk       8,  20 Mar 15  2002 sdb4
crw-rw----    1 root     audio     14,   1 Oct  7 16:26 sequencer
lrwxrwxrwx    1 root     root           10 Oct  7 16:26 sequencer2 -> /dev/music
lrwxrwxrwx    1 root     root            4 Sep 28 18:05 stderr -> fd/2
lrwxrwxrwx    1 root     root            4 Sep 28 18:05 stdin -> fd/0
lrwxrwxrwx    1 root     root            4 Sep 28 18:05 stdout -> fd/1
crw-rw-rw-    1 root     tty        5,   0 Sep 28 18:06 tty
crw-------    1 root     root       4,   0 Sep 28 18:06 tty0
crw-------    1 root     root       4,   1 Jan 19 14:59 tty1
crw-rw----    1 root     dialout   62,  64 Oct  7 06:50 ttyLT0
crw-rw----    1 root     dialout    4,  64 Mar 15  2002 ttyS0
crw-rw----    1 root     dialout    4,  65 Mar 15  2002 ttyS1
crw-rw----    1 root     dialout    4,  66 Mar 15  2002 ttyS2
crw-rw----    1 root     dialout    4,  67 Mar 15  2002 ttyS3
crw-rw----    1 root     dialout  188,   0 Mar 15  2002 ttyUSB0
crw-rw----    1 root     dialout  188,   1 Mar 15  2002 ttyUSB1
cr--r--r--    1 root     root       1,   9 Jan 19 20:46 urandom
drwxr-xr-x    2 root     root         4096 Sep 28 18:05 usb
prw-r-----    1 root     adm             0 Jan 19 14:58 xconsole
crw-rw-rw-    1 root     root       1,   5 Sep 28 18:06 zero

一些常见的设备文件以及它们在 Windows 下的等效对应项,您可能希望记住的是

/dev/ttyS0 (第一个通信端口,COM1)

第一个串行端口(鼠标、调制解调器)。

/dev/psaux (PS/2)

PS/2 鼠标连接(鼠标、键盘)。

/dev/lp0 (第一个打印机端口,LPT1)

第一个并行端口(打印机、扫描仪等)。

/dev/dsp (第一个音频设备)

名称 DSP 来自术语数字信号处理器,这是一种专门的处理器芯片,针对数字信号分析进行了优化。声卡可以使用专用的 DSP 芯片,也可以使用多个分立器件来实现这些功能。可能用于此设备的其他术语包括数字化语音和 PCM。

/dev/usb (USB 设备)

此子目录包含大多数 USB 设备节点。设备名称分配相当简单,因此无需详细说明。

/dev/sda (C:\, SCSI 设备)

第一个 SCSI 设备(HDD、记忆棒、外部大容量存储设备,例如笔记本电脑上的 CD-ROM 驱动器等)。

/dev/scd (D:\, SCSI CD-ROM 设备)

第一个 SCSI CD-ROM 设备。

/dev/js0 (标准游戏端口操纵杆)

第一个操纵杆设备。

设备由类型(例如“块”或“字符”)以及“主”编号和“次”编号定义。主编号用于对设备进行分类,次编号用于标识特定设备类型。例如,连接到主控制器的所有 IDE 设备的主编号均为 3。主设备和从设备以及各个分区通过使用次编号进一步定义。这些是在以下显示中日期之前的两个数字

# ls -l /dev/hd*

brw-rw----    1 root     disk       3,   0 Mar 15  2002 /dev/hda
brw-rw----    1 root     disk       3,   1 Mar 15  2002 /dev/hda1
brw-rw----    1 root     disk       3,  10 Mar 15  2002 /dev/hda10
brw-rw----    1 root     disk       3,  11 Mar 15  2002 /dev/hda11
brw-rw----    1 root     disk       3,  12 Mar 15  2002 /dev/hda12
brw-rw----    1 root     disk       3,  13 Mar 15  2002 /dev/hda13
brw-rw----    1 root     disk       3,  14 Mar 15  2002 /dev/hda14
brw-rw----    1 root     disk       3,  15 Mar 15  2002 /dev/hda15
brw-rw----    1 root     disk       3,  16 Mar 15  2002 /dev/hda16
brw-rw----    1 root     disk       3,  17 Mar 15  2002 /dev/hda17
brw-rw----    1 root     disk       3,  18 Mar 15  2002 /dev/hda18
brw-rw----    1 root     disk       3,  19 Mar 15  2002 /dev/hda19
brw-rw----    1 root     disk       3,   2 Mar 15  2002 /dev/hda2
brw-rw----    1 root     disk       3,  20 Mar 15  2002 /dev/hda20
brw-rw----    1 root     disk       3,   3 Mar 15  2002 /dev/hda3
brw-rw----    1 root     disk       3,   4 Mar 15  2002 /dev/hda4
brw-rw----    1 root     disk       3,   5 Mar 15  2002 /dev/hda5
brw-rw----    1 root     disk       3,   6 Mar 15  2002 /dev/hda6
brw-rw----    1 root     disk       3,   7 Mar 15  2002 /dev/hda7
brw-rw----    1 root     disk       3,   8 Mar 15  2002 /dev/hda8
brw-rw----    1 root     disk       3,   9 Mar 15  2002 /dev/hda9
brw-rw----    1 root     disk       3,  64 Mar 15  2002 /dev/hdb
brw-rw----    1 root     disk       3,  65 Mar 15  2002 /dev/hdb1
brw-rw----    1 root     disk       3,  74 Mar 15  2002 /dev/hdb10
brw-rw----    1 root     disk       3,  75 Mar 15  2002 /dev/hdb11
brw-rw----    1 root     disk       3,  76 Mar 15  2002 /dev/hdb12
brw-rw----    1 root     disk       3,  77 Mar 15  2002 /dev/hdb13
brw-rw----    1 root     disk       3,  78 Mar 15  2002 /dev/hdb14
brw-rw----    1 root     disk       3,  79 Mar 15  2002 /dev/hdb15
brw-rw----    1 root     disk       3,  80 Mar 15  2002 /dev/hdb16
brw-rw----    1 root     disk       3,  81 Mar 15  2002 /dev/hdb17
brw-rw----    1 root     disk       3,  82 Mar 15  2002 /dev/hdb18
brw-rw----    1 root     disk       3,  83 Mar 15  2002 /dev/hdb19
brw-rw----    1 root     disk       3,  66 Mar 15  2002 /dev/hdb2
brw-rw----    1 root     disk       3,  84 Mar 15  2002 /dev/hdb20
brw-rw----    1 root     disk       3,  67 Mar 15  2002 /dev/hdb3
brw-rw----    1 root     disk       3,  68 Mar 15  2002 /dev/hdb4
brw-rw----    1 root     disk       3,  69 Mar 15  2002 /dev/hdb5
brw-rw----    1 root     disk       3,  70 Mar 15  2002 /dev/hdb6
brw-rw----    1 root     disk       3,  71 Mar 15  2002 /dev/hdb7
brw-rw----    1 root     disk       3,  72 Mar 15  2002 /dev/hdb8
brw-rw----    1 root     disk       3,  73 Mar 15  2002 /dev/hdb9
brw-rw----    1 root     disk      22,   0 Mar 15  2002 /dev/hdc
brw-rw----    1 root     disk      22,  64 Mar 15  2002 /dev/hdd

hda 和 hdb 设备的主编号均为 3。当然,每个特定分区的次编号都会更改。可以通过查看 /usr/src/linux/include/linux/major.h 文件的内容来检查每个主编号类别的定义。devices.txt 也记录了主编号和次编号。它位于 /usr/src/linux/Documentation 目录中。此文件定义了主编号。几乎所有文件设备都在安装时默认创建。但是,您始终可以使用 mknod 命令或位于 /dev 目录本身的 MAKEDEV 脚本来创建设备。可以使用此实用程序创建设备,方法是提供要创建的设备、设备类型(块或字符)以及主编号和次编号。例如,假设您不小心删除了 /dev/ttyS0(Windows 下的 COM1),可以使用以下命令重新创建它

# mknod ttyS0 c 4 64

对于我们这些比较懒惰的人来说,您可以简单地运行 MAKEDEV 脚本,如下所示

# MAKEDEV *

这将创建所有已知的设备。

可能 /dev 也可能包含 MAKEDEV.local,用于创建任何本地设备文件。

一般来说,并且按照 FSSTND 的要求,MAKEDEV 将提供创建系统上可能找到的任何设备的功能,而不仅仅是特定实现安装的那些设备。

对于那些想知道为什么 Linux 使用如此原始的系统来引用设备的人来说,这是因为我们还没有能够设计出一种足够复杂的机制,该机制能够提供足够多的优势来超越当前系统,从而实现广泛采用。

迄今为止(截至内核版本 2.4),CSIRO 的 Richard Gooch 已经做出了最好的尝试。它被称为 devfsd,并且已经成为内核的一部分多年。它已获得内核开发人员和 Linus 本人的认可,其实现的详细信息可以在 /usr/src/linux/Documentation/filesystems/devfs/README 中找到。以下是本文档的摘录。

Devfs 是“真实”字符和块特殊设备在您的根文件系统上的替代方案。内核设备驱动程序可以通过名称而不是主编号和次编号来注册设备。这些设备将自动出现在 devfs 中,并带有驱动程序指定的任何默认所有权和保护。守护进程 (devfsd) 可用于覆盖这些默认值。Devfs 自 2.3.46 内核以来就已存在。

请注意,devfs 是完全可选的。如果您喜欢旧的基于磁盘的设备节点,那么只需保留 CONFIG_DEVFS_FS=n(默认值)。在这种情况下,一切都不会改变。另请注意,如果您确实启用了 devfs,则默认设置会保持与旧设备名称的完全兼容性。

devfs 有两个方面:一个是底层设备命名空间,它就像任何已挂载的文件系统一样是一个命名空间。另一方面是文件系统代码,它提供了设备命名空间的视图。我之所以区分,是因为 devfs 可以多次挂载,每次挂载都显示相同的设备命名空间。所做的更改对所有已挂载的 devfs 文件系统都是全局的。此外,由于 devfs 命名空间在没有任何 devfs 挂载的情况下存在,因此您可以通过引用 devfs 命名空间中的条目轻松挂载根文件系统。

devfs 的代价是内核代码大小和内存使用量略有增加。大约 7 页代码(其中一些在 __init 部分)和命名空间中每个条目 72 字节。一个适度的系统只有几百个设备条目,因此这会增加几页。将此与将 /dev 放在 ramdisk 上的建议进行比较。

在典型的机器上,成本低于 0.2%。在具有 64 MB RAM 的适度系统上,成本低于 0.1%。对 devfs 的“臃肿软件”指责是不合理的。

截至内核版本 2.6,devfs 已被标记为过时,现在已被 udev 取代。udev 是一个非常相似的系统(至少从最终用户的角度来看),但在用户空间中完全工作。有关 udev 的概述,请访问 http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf