一、从 /dev 目录看设备
在 Linux 系统中,绝大多数设备都通过 设备文件(device file) 的形式暴露在 /dev 目录下。 这些设备文件本质上是“访问设备的入口”,而不是真正存储数据的普通文件。
在开发板上执行 ls -l /dev, 会看到类似于下面的输出:
lckfb@linaro-alip:~$ ls -l /dev
总计 8
drwxr-xr-x 3 root root 480 12月 9日 19:02 block
drwxr-xr-x 3 root root 60 1970年 1月 1日 bus
crw-rw---- 1 root video 248, 0 12月 9日 19:02 cec0
drwxr-xr-x 2 root root 5300 12月 9日 19:02 char
crw--w---- 1 root tty 5, 1 12月 9日 19:03 console
crw------- 1 root root 10, 124 12月 9日 19:02 cpu_dma_latency
crw-rw-rw- 1 root root 10, 126 12月 9日 19:02 crypto
drwxr-xr-x 9 root root 180 12月 9日 19:02 disk
drwxr-xr-x 2 root root 100 1970年 1月 1日 dma_heap
drwxr-xr-x 3 root root 140 12月 9日 19:02 dri
crw------- 1 root root 240, 0 12月 9日 19:02 drm_dp_aux0
lrwxrwxrwx 1 root root 13 12月 9日 19:02 fd -> /proc/self/fd
crw-rw-rw- 1 root root 1, 7 12月 9日 19:02 full
crw-rw-rw- 1 root root 10, 229 12月 9日 19:02 fuse
crw------- 1 root root 254, 0 12月 9日 19:02 gpiochip0
crw------- 1 root root 254, 1 12月 9日 19:02 gpiochip1
..........
crw------- 1 root root 10, 183 12月 9日 19:02 hwrng
crw-rw---- 1 root i2c 89, 1 12月 9日 19:02 i2c-1
crw-rw---- 1 root i2c 89, 10 12月 9日 19:02 i2c-10
.........
crw------- 1 root root 245, 0 12月 9日 19:02 iio:device0
lrwxrwxrwx 1 root root 12 12月 9日 19:02 initctl -> /run/initctl
drwxr-xr-x 3 root root 180 12月 9日 19:02 input
crw-r--r-- 1 root root 1, 11 12月 9日 19:02 kmsg
lrwxrwxrwx 1 root root 28 12月 9日 19:02 log -> /run/systemd/journal/dev-log
brw-rw---- 1 root disk 7, 0 12月 9日 19:02 loop0
................
crw-rw---- 1 root disk 10, 237 12月 9日 19:02 loop-control
crw-rw---- 1 root video 10, 122 12月 9日 19:02 mali0
crw-rw----+ 1 root video 249, 0 12月 9日 19:02 media0
crw-rw----+ 1 root video 249, 1 12月 9日 19:02 media1
.....................
crw-r----- 1 root kmem 1, 1 12月 9日 19:02 mem
brw-rw---- 1 root disk 179, 0 12月 9日 19:02 mmcblk0
brw-rw---- 1 root disk 179, 32 12月 9日 19:02 mmcblk0boot0
brw-rw---- 1 root disk 179, 64 12月 9日 19:02 mmcblk0boot1
brw-rw---- 1 root disk 179, 1 12月 9日 19:02 mmcblk0p1
brw-rw---- 1 root disk 179, 2 12月 9日 19:02 mmcblk0p2
brw-rw---- 1 root disk 179, 3 12月 9日 19:02 mmcblk0p3
brw-rw---- 1 root disk 179, 4 12月 9日 19:02 mmcblk0p4
brw-rw---- 1 root disk 179, 5 12月 9日 19:02 mmcblk0p5
brw-rw---- 1 root disk 179, 6 12月 9日 19:02 mmcblk0p6
brw-rw---- 1 root disk 179, 7 12月 9日 19:02 mmcblk0p7
brw-rw---- 1 root disk 179, 8 12月 9日 19:02 mmcblk0p8
crw------- 1 root root 235, 0 12月 9日 19:02 mmcblk0rpmb
crw-rw---- 1 root video 241, 0 12月 9日 19:02 mpp_service
crw-rw-rw- 1 root root 1, 3 12月 9日 19:02 null
crw-r----- 1 root kmem 1, 4 12月 9日 19:02 port
crw-rw-rw- 1 root tty 5, 2 12月12日 14:34 ptmx
crw------- 1 root root 246, 0 12月 9日 19:02 ptp0
drwxr-xr-x 2 root root 0 12月 9日 19:02 pts
brw-rw---- 1 root disk 1, 0 12月 9日 19:02 ram0
crw-rw-rw- 1 root root 1, 8 12月 9日 19:02 random
crw-rw-r--+ 1 root netdev 10, 242 12月 9日 19:02 rfkill
crw-rw---- 1 root video 10, 123 12月 9日 19:02 rga
lrwxrwxrwx 1 root root 4 12月 9日 19:02 rtc -> rtc0
crw------- 1 root root 250, 0 12月 9日 19:02 rtc0
drwxrwxrwt 2 root root 40 12月 9日 19:02 shm
drwxr-xr-x 3 root root 260 12月 9日 19:02 snd
lrwxrwxrwx 1 root root 15 12月 9日 19:02 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 12月 9日 19:02 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 12月 9日 19:02 stdout -> /proc/self/fd/1
crw------- 1 root root 10, 127 12月 9日 19:02 sw_sync
crw------- 1 root root 244, 0 12月 9日 19:02 tee0
crw------- 1 root root 244, 16 12月 9日 19:02 teepriv0
crw-rw-rw- 1 root tty 5, 0 12月 9日 19:02 tty
crw--w---- 1 root tty 4, 0 12月 9日 19:02 tty0
crw--w---- 1 root tty 4, 1 12月 9日 19:02 tty1
..................
crw------- 1 root root 10, 121 12月 9日 19:02 ubi_ctrl
crw------- 1 root root 10, 239 12月 9日 19:02 uhid
crw------- 1 root root 10, 223 12月 9日 19:02 uinput
crw-rw-rw- 1 root root 1, 9 12月 9日 19:02 urandom
drwxr-xr-x 3 root root 60 12月 9日 19:02 usb-ffs
crw------- 1 root root 237, 0 12月 9日 19:02 usbmon0
crw------- 1 root root 237, 1 12月 9日 19:02 usbmon1
crw------- 1 root root 237, 2 12月 9日 19:02 usbmon2
drwxr-xr-x 3 root root 60 12月 9日 19:02 v4l
crw-rw----+ 1 root video 81, 65 12月 9日 19:02 v4l-subdev0
crw-rw----+ 1 root video 81, 70 12月 9日 19:02 v4l-subdev1
..................
crw-rw---- 1 root tty 7, 0 12月 9日 19:02 vcs
crw-rw---- 1 root tty 7, 1 12月 9日 19:02 vcs1
.................
crw-rw---- 1 root tty 7, 70 12月 9日 19:02 vcsu6
crw-rw---- 1 root tty 7, 71 12月 9日 19:02 vcsu7
crw------- 1 root root 10, 125 12月 9日 19:02 vendor_storage
crw------- 1 root root 10, 137 12月 9日 19:02 vhci
crw-rw----+ 1 root video 81, 0 12月 9日 19:02 video0
crw-rw----+ 1 root video 81, 1 12月 9日 19:02 video1
.................
crw------- 1 root root 10, 130 12月 9日 19:02 watchdog
crw------- 1 root root 243, 0 12月 9日 19:02 watchdog0
crw-rw-rw- 1 root root 1, 5 12月 9日 19:02 zero
brw-rw---- 1 root disk 254, 0 12月 9日 19:02 zram02
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
其中最主要的的就是:
- 第一行字母(设备类型):
crw-rw-rw- 1 root root 1, 3 12月 9日 19:02 null
^
|
文件类型:c = 字符设备 (character device)
brw-rw---- 1 root disk 179, 0 12月 9日 19:02 mmcblk0
^
|
文件类型:b = 块设备 (block device)2
3
4
5
6
7
8
9
c:字符设备(character device)b:块设备(block device)d:目录(directory)l:符号链接(symlink)- 其他类型此处暂不展开
对于驱动开发者而言,最常打交道的是:
c开头的 字符设备(如/dev/null、/dev/ttyS0、/dev/gpiochip0等)b开头的 块设备(如/dev/mmcblk0、/dev/zram0等)
- 倒数第3和第2列的一对数字(主次设备号):
crw-rw-rw- 1 root root 1, 3 12月 9日 19:02 null
^ ^
| |
主设备号 次设备号2
3
4
这两个数字共同构成该设备的设备号(device number),用于在内核中唯一标识设备及对应驱动。 例如:
/dev/null:1, 3/dev/mmcblk0:179, 0后续章节会专门介绍主设备号与次设备号的含义、分配方式,以及驱动程序如何注册和使用。
二、按访问方式分类
Linux 中最基础的分类是按照访问方式,将设备分为:
- 字符设备(Character Device)
- 块设备(Block Device)
1. 字符设备
字符设备(Character Device)以 字节流(stream) 的方式进行顺序读写:
- 一般不要求对齐到固定大小的 “ 块 ” 。
- 通常不带复杂的缓冲和随机访问优化。
典型示例:
- 串口终端:
/dev/ttyS0、/dev/ttyUSB0 - 控制台:
/dev/console - 一些简单的控制类或调试类设备:
/dev/null、/dev/zero、/dev/random - 用户自定义的字符设备:
/dev/mychar等
在 ls -l 输出中:
- 以
c开头:
crw-rw---- 1 root dialout 4, 64 ... /dev/ttyS0用户空间通常使用 open / read / write / ioctl 等系统调用访问字符设备:
int fd = open("/dev/ttyS0", O_RDWR);
write(fd, buf, len);
read(fd, buf, len);
close(fd);2
3
4
后续章节将重点围绕这一类设备展开。
2. 块设备
块设备(Block Device)以数据块(block)为单位读写,块大小通常为 512 字节或其倍数。 特点:
- 支持高效的随机访问和缓存机制。
- 主要用于各种存储介质。
典型示例:
- eMMC / SD 卡:
/dev/mmcblk0、/dev/mmcblk0p1 - U 盘、SATA/USB 磁盘:
/dev/sda、/dev/sdb
在 ls -l 输出中:
- 以
b开头:
brw-rw---- 1 root disk 179, 0 12月 9日 19:02 /dev/mmcblk0通常不会直接对块设备进行高层数据读写,而是:
- 在块设备之上建立文件系统(如 ext4、vfat);
- 将其挂载到某个目录:
mount /dev/mmcblk0p1 /mnt- 通过普通文件接口访问
/mnt下的文件。
块设备驱动与文件系统配合使用,涉及内容较多,此章节重点不在此。
三、网络设备与其它类型
字符设备和块设备主要通过 /dev 暴露给用户空间。
除此之外,还有一些不以传统设备文件形式呈现的设备类型,主要通过专门的子系统使用。
1. 网络设备
网络设备(Network Device),例如以太网、WiFi等通常以 网络接口 的形式出现:
- 例如:
eth0、end0、wlan0、lo等。 - 可以通过以下命令查看:
ip link show网络设备:
- 不对应普通的
/dev设备文件。 - 通过 socket 接口与内核网络子系统交互,例如:
socket(AF_INET, SOCK_STREAM, 0);网络驱动通常实现 struct net_device 相关接口,属于单独的子系统,本教程暂不展开。
2. 其他设备等
某些设备类型在内核中有专门框架,并通过特定方式暴露给用户空间:
- 输入设备(键盘、触摸屏等):
- 底层通常为字符设备:
/dev/input/eventX - 用户空间多通过
libinput、Xorg、Wayland 等上层库使用。
- 底层通常为字符设备:
- 声音设备:
- ALSA 框架:如
/dev/snd/* - 提供 PCM、控制等多种接口。
- ALSA 框架:如
- 图形设备(GPU / 显卡):
- DRM/KMS 体系:如
/dev/dri/card0
- DRM/KMS 体系:如
这类设备在内核内部一般仍然基于字符设备或其他抽象,但对外通过各自子系统和 API 使用。
四、从sysfs视角看设备分类
除了 /dev,现代 Linux 内核还通过 sysfs(通常挂载在 /sys)对设备进行分层组织和展示。
在开发板上使用 ls /sys/class/:
lckfb@linaro-alip:~$ ls /sys/class/
android_usb devcoredump dvb input net pwm scsi_disk tpm usb_role
ata_device devfreq extcon iommu nvme regulator scsi_host tpmrm vc
ata_link devfreq-event gpio leds nvme-generic retimer sound tty video4linux
ata_port devlink hdmirx mdio_bus nvme-subsystem rfkill spidev typec vtconsole
backlight dma hidraw mem pci_bus rk_modem spi_host typec_mux wakeup
bdi dma_heap hwmon misc phy rkwifi spi_master ubi watchdog
block drm i2c-adapter mmc_host power_supply rpmsg spi_transport udc zram-control
bluetooth drm_dp_aux_dev i2c-dev mpp_class pps rtc tee usbmon
bsg dsmc ieee80211 mtd ptp scsi_device thermal usb_power_delivery2
3
4
5
6
7
8
9
10
可见典型目录,例如:
block:块设备类tty:终端/串口类设备net:网络接口input:输入设备类mmc_host:MMC 主控制器
这些目录下的类(class)代表一种设备类型或子系统; 类下的每个条目对应一个具体设备实例,并通过符号链接与 /sys/devices 中的物理设备关联。
后续章节将对此做详细介绍。
六、小结
- Linux 中常见设备分类:
- 字符设备(character device):以字节/流的方式访问,例如串口、部分控制类设备;
- 块设备(block device):以固定大小数据块访问,主要用于各种存储介质;
- 还有网络设备、输入设备、声音设备等,通过专门子系统和接口使用。
- 在
/dev中:c开头的设备文件表示字符设备;b开头的设备文件表示块设备;- 后面的主、次设备号用于唯一标识设备与对应驱动。
- 在
/sys/class中,可以从设备模型角度观察不同类型设备的组织方式。