概述
设备管理是 Linux 中比较基础的知识,与内核的关系也比较密切。随着 Udev 的广泛使用,Linux 发行版的智能程度越来越高,许多 Linux 新用户对 /dev 目录下的东西变得不再熟悉,有时候遇见问题就会抓狂。
Linux 中的设备按照存取方式的不同,可以分为两种:
-
字符设备
- 无缓冲且只能顺序存取 块设备
- 有缓冲且可以随机(乱序)存取
而按照是否对应物理实体,也可以分为两种:
-
物理设备
- 对实际存在的物理硬件的抽象 虚拟设备
- 不依赖于特定的物理硬件,仅是内核自身提供的某种功能
无论是哪种设备,在 /dev 目录下都有一个对应的文件(节点),并且每个设备文件都必须有主/次设备号,主设备号相同的设备是同类设备,使用同一个驱动程序(虽然目前的内核允许多个驱动共享一个主设备号,但绝大多数设备依然遵循一个驱动对应一个主设备号的原则)。可以通过 cat /proc/devices 命令查看当前已经加载的设备驱动程序的主设备号。
内核能够识别的所有设备都记录在原码树下的 Documentation/devices.txt 文件中。另外,在 http://www.lanana.org/docs/device-list/ 也有一份,貌似已经失去维护。
注意:在 /dev 目录下除了各种设备节点之外还通常还会存在:FIFO管道、Socket、软/硬连接、目录。这些东西并不是设备文件,因此也就没有主/次设备号。
设备文件
了解这些设备的最基本要求就是对每个设备文件的含义了如指掌,下面列出了 Linux-3.13.2 内核中常见的已注册设备及其含义(省略了生僻与罕见的设备)。
---------------------------------------------------------------------- 主设备号 设备类型 次设备号=文件名 简要说明 ---------------------------------------------------------------------- 0 未命名设备(例如NFS之类非设备的挂载) 0 = 为空设备号保留 参见主设备号为144,145,146的块设备,以了解"扩展区域"(expansion area) 1 char 内存设备 1 = /dev/mem 物理内存的全镜像。可以用来直接存取物理内存。 2 = /dev/kmem 内核看到的虚拟内存的全镜像。可以用来访问内核中的内容(查看内核变量或用作rootkit之类)。 3 = /dev/null 空设备。任何写入都将被直接丢弃(但返回"成功");任何读取都将得到EOF(文件结束标志)。 4 = /dev/port 存取I/O端口 5 = /dev/zero 零流源。任何写入都将被直接丢弃(但返回"成功");任何读取都将得到无限多的二进制零流。 7 = /dev/full 满设备。任何写入都将失败,并把errno设为ENOSPC(没有剩余空间);任何读取都将得到无限多的二进制零流。 这个设备通常被用来测试程序在遇到磁盘无剩余空间错误时的行为。 8 = /dev/random 真随机数发生器。以背景噪声数据或硬件随机数发生器作为熵池,读取时会返回小于熵池噪声总数的随机字节。 若熵池空了,读操作将会被阻塞,直到收集到了足够的环境噪声为止。建议用于需要生成高强度密钥的场合。 [注意]虽然允许写入,但企图通过写入此文件来"预存"随机数是徒劳的,因为写入的数据对输出并无影响。 9 = /dev/urandom 伪随机数发生器。更快,但是不够安全。仅用于对安全性要求不高的场合。 即使熵池空了,读操作也不会被阻塞,而是把已经产生的随机数做为种子来产生新的随机数。 [注意]虽然允许写入,但企图通过写入此文件来"预存"随机数是徒劳的,因为写入的数据对输出并无影响。 10 = /dev/aio 异步I/O通知接口 11 = /dev/kmsg 任何对该文件的写入都将作为printk的输出;而读取则得到printk的输出缓冲区内容。 1 block RAM disk [已过时,请用TMPFS] 0 = /dev/ram0 第1个 RAM disk 1 = /dev/ram1 第2个 RAM disk ... [说明]将/dev/ram0用作initrd的做法已过时(因为它仅针对image-initrd格式),当下的主流是cpio-initrd格式。 4 char TTY(终端)设备 0 = /dev/tty0 当前虚拟控制台 1 = /dev/tty1 第1个虚拟控制台 ... 63 = /dev/tty63 第63个虚拟控制台 64 = /dev/ttyS0 第1个UART串口 ... 255 = /dev/ttyS191 第192个UART串口 [说明]"UART串口"是指 8250/16450/16550 UART串行控制芯片 4 block 如果根文件系统以是以只读方式挂载的,那么就不可能创建真正的设备节点, 此时就使用该设备作为动态分配的主设备的别名,并挂载为根文件系统。 0 = /dev/root 5 char 辅助 TTY 设备 0 = /dev/tty 当前 TTY 设备 1 = /dev/console 系统控制台(一般是/dev/tty0) 2 = /dev/ptmx 所有 Unix98 PTY master 的复用器 3 = /dev/ttyprintk 内核通过此设备使用printk发送内嵌的用户消息(依赖于CONFIG_TTY_PRINTK) 64 = /dev/cua0 对应于 ttyS0 的呼出(Callout)设备 ... 255 = /dev/cua191 对应于 ttyS191 的呼出(Callout)设备 7 char 虚拟控制台捕捉设备(这些设备既允许读也允许写) 0 = /dev/vcs 当前虚拟控制台(vc)的文本内容 1 = /dev/vcs1 tty1 的文本内容 ... 63 = /dev/vcs63 tty63 的文本内容 128 = /dev/vcsa 当前虚拟控制台(vc)的文本/属性内容 129 = /dev/vcsa1 tty