linux设备管理之主设备号与次设备号


主设备号和次设备号

一个字符设备或者块设备都有一个主设备号和次设备号。主设备号和次设备号统称为设备号。
主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各设备。
在同一个系统中,一类设备的主设备号是唯一的。次设备号只是在驱动程序内部使用,系统内核直接把次设备号传递给应用程序,由驱动程序管理。为了保证驱动程序的通用性,避免驱动程序移植过程中出现主设备号冲突,系统为设备编了号,每个设备号又分为主设备号和次设备号。主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号。
注: 主设备号和次设备号,在不同磁盘的工具中都有输出显示,所以对于这个概念的理解还是很重要,否则你看不懂很多命令的输出。
尤其是 cat /proc/devices 输出的意义等。

设备的分类

以 Linux 的方式看待设备可区分为 3 种基本设备类型。 每个设备常常实现 3 种类型中的 1 种, 因此可分类成字符设备, 块设备, 或者一个网络设备。这种将设备分成不同类型或类别的方法并非是固定不变的。

1、字符设备

一个字符( char ) 设备是一种可以当作一个字节流来存取的设备( 如同一个文件 ); 字符驱动模块负责实现这种行为。
这样的驱动模块至少实现 open, close, read, 和 write 系统调用。文本控制台( /dev/console )和串口( /dev/ttyS0 及其他 )是字符设备的例子, 因为它们很好地展现了流的抽象。字符设备通过文件系统结点来存取, 例如 /dev/tty1 和 /dev/lp0。

2、块设备

如同字符设备, 块设备通过位于 /dev 目录的文件系统结点来存取. 一个块设备(例如一个磁盘)应该是可以驻有一个文件系统的。
在大部分的 Unix 系统, 一个块设备只能处理特定的 I/O 操作, 即传送一个或多个长度经常是 512 字节( 或一个更大的 2 的幂的数 )的整块。
Linux, 相反, 允许应用程序读写一个块设备象一个字符设备一样;它允许一次传送任意数目的字节。 结果就是, 块和字符设备的区别仅仅在内核内部管理数据的方式上, 和在内核/驱动的软件接口上不同。
如同一个字符设备, 每个块设备都通过一个文件系统结点被存取的, 它们之间的区别对用户是透明的。 块驱动和字符驱动相比, 与内核的接口完全不同。

3、网络接口设备

任何网络事务都通过一个接口来进行, 就是说, 一个能够与其他主机交换数据的设备。
通常, 一个接口是一个硬件设备, 但是它也可能是一个纯粹的软件设备, 比如环回接口。一个网络接口负责发送和接收数据报文, 在内核网络子系统的驱动下, 不必知道单个事务是如何映射到实际的被发送的报文上的。很多网络连接( 特别那些使用 TCP 的)是面向流的, 但是网络设备却常常设计成处理报文的发送和接收。网络驱动对单个连接一无所知; 它只处理报文。

设备名称

fb::frame缓冲
fd:—–:软驱
hd:—–:IDE 硬盘/光驱
md:—–:RAID设备(Metadisk)
dm:—–:LVM设备(DeviceMapper)
xd:—–:虚拟机中的硬盘驱动器
tty:—–:终端设备
psaux:—–:PS/2 鼠标设备
lp:—–:打印机
par:—–:并口
pt:—–:伪终端
s:—–:SCSI设备
scd:—–:SCSI音频光驱
sd:—–:SCSI硬盘
sg:—–:SCSI通用设备
sr:—–:SCSI数据光驱
st:—–:SCSI磁带
cdrom:—–:光驱的符号链接
mouse:—–:鼠标设备的符号链接
gpmdata:—–:伪设备
null:—–:写入消失
zero:—–:一直产生零

 

linux 系统下查找下主设备号

linux 系统采样
[root@fp-web-130 src]# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core)

[root@fp-web-130 src]# cat /proc/devices
//显示结果

Character devices:  //字符设备
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
21 sg
29 fb
99 ppdev
128 ptm
136 pts
162 raw
180 usb
188 ttyUSB
189 usb_device
202 cpu/msr
203 cpu/cpuid
226 drm
249 hidraw
250 usbmon
251 bsg
252 watchdog
253 rtc
254 tpm

Block devices:  //块设备
259 blkext
7 loop   //回环设备
8 sd     //scsi设备
9 md
11 sr    //只读光驱
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
说明: sd,md,loop等就是设备名

实例:lsblk 命令可以查看块设备的主设备号和次设备号



解释:
loop0 的主设备号是 7:0 7表示的主设备号,0是系统为loop0回环设备编了号.这个主从就表示了唯一性([root@fp-web-130 src]# cat /proc/devices 得到的回环设备loop是7)
loop1 的主设备号是 7:1 7表示的主设备号,1是系统为loop1回环设备编了号.

基本上如果主设备号和次设备号明白了,那么lsblk这个命令的基本输出结果理解上就没有难度了


为了使应用程序区分所控制设备的类型,内核使用主设备号。而存在多台同类设备时,为了选择其中的一种,设备驱动程序就使用次设备号
举例: 这里sd是8(cat /proc/devices查的),看到有一列是8,16 这里8就是主设备号、16就是次设备号 


linux下次设备号查看

[root@fp-web-130 src]# ls -l /dev
total 0
crw-rw---- 1 root video 10, 175 May 27 2021 agpgart
crw------- 1 root root 10, 235 May 27 2021 autofs
drwxr-xr-x 2 root root 340 Feb 9 00:02 block
drwxr-xr-x 2 root root 140 May 27 2021 bsg
crw------- 1 root root 10, 234 May 27 2021 btrfs-control
lrwxrwxrwx 1 root root 3 May 27 2021 cdrom -> sr0
drwxr-xr-x 2 root root 80 May 27 2021 centos
drwxr-xr-x 2 root root 3000 May 27 2021 char
crw------- 1 root root 5, 1 May 27 2021 console
lrwxrwxrwx 1 root root 11 May 27 2021 core -> /proc/kcore
drwxr-xr-x 10 root root 220 May 27 2021 cpu
crw------- 1 root root 10, 61 May 27 2021 cpu_dma_latency
crw------- 1 root root 10, 62 May 27 2021 crash
drwxr-xr-x 5 root root 100 May 27 2021 disk
brw-rw---- 1 root disk 253, 0 May 27 2021 dm-0
brw-rw---- 1 root disk 253, 1 May 27 2021 dm-1
brw-rw---- 1 root disk 253, 2 Feb 7 14:58 dm-2
brw-rw---- 1 root disk 253, 3 Feb 7 14:58 dm-3
drwxr-xr-x 2 root root 100 May 27 2021 dri
crw-rw---- 1 root video 29, 0 May 27 2021 fb0
lrwxrwxrwx 1 root root 13 May 27 2021 fd -> /proc/self/fd
crw-rw-rw- 1 root root 1, 7 May 27 2021 full
crw-rw-rw- 1 root root 10, 229 May 27 2021 fuse
crw------- 1 root root 10, 228 May 27 2021 hpet
drwxr-xr-x 2 root root 0 May 27 2021 hugepages
lrwxrwxrwx 1 root root 25 May 27 2021 initctl -> /run/systemd/initctl/fifo
drwxr-xr-x 3 root root 180 May 27 2021 input
crw-r--r-- 1 root root 1, 11 May 27 2021 kmsg
srw-rw-rw- 1 root root 0 May 27 2021 log
brw-rw---- 1 root disk 7, 0 Feb 7 14:58 loop0
brw-rw---- 1 root disk 7, 1 Feb 7 14:58 loop1
brw-rw---- 1 root disk 7, 2 Feb 9 11:21 loop2
crw-rw---- 1 root disk 10, 237 May 27 2021 loop-control
drwxr-xr-x 2 root root 140 Feb 7 14:58 mapper
crw------- 1 root root 10, 227 May 27 2021 mcelog
crw-r----- 1 root kmem 1, 1 May 27 2021 mem
drwxrwxrwt 2 root root 40 May 27 2021 mqueue
drwxr-xr-x 2 root root 60 May 27 2021 net
crw------- 1 root root 10, 60 May 27 2021 network_latency
crw------- 1 root root 10, 59 May 27 2021 network_throughput
crw-rw-rw- 1 root root 1, 3 May 27 2021 null
crw------- 1 root root 10, 144 May 27 2021 nvram
crw------- 1 root root 1, 12 May 27 2021 oldmem
crw-r----- 1 root kmem 1, 4 May 27 2021 port
crw------- 1 root root 108, 0 May 27 2021 ppp
crw-rw-rw- 1 root tty 5, 2 Feb 9 15:03 ptmx
drwxr-xr-x 2 root root 0 May 27 2021 pts
crw-rw-rw- 1 root root 1, 8 May 27 2021 random
drwxr-xr-x 2 root root 60 May 27 2021 raw
lrwxrwxrwx 1 root root 4 May 27 2021 rtc -> rtc0
crw------- 1 root root 253, 0 May 27 2021 rtc0
brw-rw---- 1 root disk 8, 0 May 27 2021 sda
brw-rw---- 1 root disk 8, 1 May 27 2021 sda1
brw-rw---- 1 root disk 8, 2 May 27 2021 sda2
brw-rw---- 1 root disk 8, 16 Feb 5 01:02 sdb
brw-rw---- 1 root disk 8, 17 Feb 5 01:02 sdb1
brw-rw---- 1 root disk 8, 18 Feb 5 01:02 sdb2
brw-rw---- 1 root disk 8, 21 Feb 5 01:04 sdb5
crw-rw---- 1 root cdrom 21, 0 May 27 2021 sg0
crw-rw---- 1 root disk 21, 1 May 27 2021 sg1
crw-rw---- 1 root disk 21, 2 May 27 2021 sg2
drwxrwxrwt 2 root root 40 May 27 2021 shm
crw------- 1 root root 10, 231 May 27 2021 snapshot
drwxr-xr-x 2 root root 80 May 27 2021 snd
brw-rw---- 1 root cdrom 11, 0 May 27 2021 sr0
lrwxrwxrwx 1 root root 15 May 27 2021 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 27 2021 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 May 27 2021 stdout -> /proc/self/fd/1
crw-rw-rw- 1 root tty 5, 0 May 27 2021 tty
crw--w---- 1 root tty 4, 0 May 27 2021 tty0
crw--w---- 1 root tty 4, 1 May 27 2021 tty1
crw--w---- 1 root tty 4, 10 May 27 2021 tty10
crw--w---- 1 root tty 4, 11 May 27 2021 tty11
crw--w---- 1 root tty 4, 12 May 27 2021 tty12
crw--w---- 1 root tty 4, 13 May 27 2021 tty13
crw--w---- 1 root tty 4, 14 May 27 2021 tty14
crw--w---- 1 root tty 4, 15 May 27 2021 tty15
crw--w---- 1 root tty 4, 16 May 27 2021 tty16
crw--w---- 1 root tty 4, 17 May 27 2021 tty17
crw--w---- 1 root tty 4, 18 May 27 2021 tty18
crw--w---- 1 root tty 4, 19 May 27 2021 tty19
crw--w---- 1 root tty 4, 2 May 27 2021 tty2
crw--w---- 1 root tty 4, 20 May 27 2021 tty20
crw--w---- 1 root tty 4, 21 May 27 2021 tty21
crw--w---- 1 root tty 4, 22 May 27 2021 tty22
crw--w---- 1 root tty 4, 23 May 27 2021 tty23
crw--w---- 1 root tty 4, 24 May 27 2021 tty24
crw--w---- 1 root tty 4, 25 May 27 2021 tty25
crw--w---- 1 root tty 4, 26 May 27 2021 tty26
crw--w---- 1 root tty 4, 27 May 27 2021 tty27
crw--w---- 1 root tty 4, 28 May 27 2021 tty28
crw--w---- 1 root tty 4, 29 May 27 2021 tty29
crw--w---- 1 root tty 4, 3 May 27 2021 tty3
crw--w---- 1 root tty 4, 30 May 27 2021 tty30
crw--w---- 1 root tty 4, 31 May 27 2021 tty31
crw--w---- 1 root tty 4, 32 May 27 2021 tty32
crw--w---- 1 root tty 4, 33 May 27 2021 tty33
crw--w---- 1 root tty 4, 34 May 27 2021 tty34
crw--w---- 1 root tty 4, 35 May 27 2021 tty35
crw--w---- 1 root tty 4, 36 May 27 2021 tty36
crw--w---- 1 root tty 4, 37 May 27 2021 tty37
crw--w---- 1 root tty 4, 38 May 27 2021 tty38
crw--w---- 1 root tty 4, 39 May 27 2021 tty39
crw--w---- 1 root tty 4, 4 May 27 2021 tty4
crw--w---- 1 root tty 4, 40 May 27 2021 tty40
crw--w---- 1 root tty 4, 41 May 27 2021 tty41
crw--w---- 1 root tty 4, 42 May 27 2021 tty42
crw--w---- 1 root tty 4, 43 May 27 2021 tty43
crw--w---- 1 root tty 4, 44 May 27 2021 tty44
crw--w---- 1 root tty 4, 45 May 27 2021 tty45
crw--w---- 1 root tty 4, 46 May 27 2021 tty46
crw--w---- 1 root tty 4, 47 May 27 2021 tty47
crw--w---- 1 root tty 4, 48 May 27 2021 tty48
crw--w---- 1 root tty 4, 49 May 27 2021 tty49
crw--w---- 1 root tty 4, 5 May 27 2021 tty5
crw--w---- 1 root tty 4, 50 May 27 2021 tty50
crw--w---- 1 root tty 4, 51 May 27 2021 tty51
crw--w---- 1 root tty 4, 52 May 27 2021 tty52
crw--w---- 1 root tty 4, 53 May 27 2021 tty53
crw--w---- 1 root tty 4, 54 May 27 2021 tty54
crw--w---- 1 root tty 4, 55 May 27 2021 tty55
crw--w---- 1 root tty 4, 56 May 27 2021 tty56
crw--w---- 1 root tty 4, 57 May 27 2021 tty57
crw--w---- 1 root tty 4, 58 May 27 2021 tty58
crw--w---- 1 root tty 4, 59 May 27 2021 tty59
crw--w---- 1 root tty 4, 6 May 27 2021 tty6
crw--w---- 1 root tty 4, 60 May 27 2021 tty60
crw--w---- 1 root tty 4, 61 May 27 2021 tty61
crw--w---- 1 root tty 4, 62 May 27 2021 tty62
crw--w---- 1 root tty 4, 63 May 27 2021 tty63
crw--w---- 1 root tty 4, 7 May 27 2021 tty7
crw--w---- 1 root tty 4, 8 May 27 2021 tty8
crw--w---- 1 root tty 4, 9 May 27 2021 tty9
crw-rw---- 1 root dialout 4, 64 May 27 2021 ttyS0
crw-rw---- 1 root dialout 4, 65 May 27 2021 ttyS1
crw-rw---- 1 root dialout 4, 66 May 27 2021 ttyS2
crw-rw---- 1 root dialout 4, 67 May 27 2021 ttyS3
crw------- 1 root root 10, 239 May 27 2021 uhid
crw------- 1 root root 10, 223 May 27 2021 uinput
crw-rw-rw- 1 root root 1, 9 May 27 2021 urandom
crw------- 1 root root 250, 0 May 27 2021 usbmon0
crw-rw---- 1 root tty 7, 0 May 27 2021 vcs
crw-rw---- 1 root tty 7, 1 May 27 2021 vcs1
crw-rw---- 1 root tty 7, 2 May 27 2021 vcs2
crw-rw---- 1 root tty 7, 3 May 27 2021 vcs3
crw-rw---- 1 root tty 7, 4 May 27 2021 vcs4
crw-rw---- 1 root tty 7, 5 May 27 2021 vcs5
crw-rw---- 1 root tty 7, 6 May 27 2021 vcs6
crw-rw---- 1 root tty 7, 128 May 27 2021 vcsa
crw-rw---- 1 root tty 7, 129 May 27 2021 vcsa1
crw-rw---- 1 root tty 7, 130 May 27 2021 vcsa2
crw-rw---- 1 root tty 7, 131 May 27 2021 vcsa3
crw-rw---- 1 root tty 7, 132 May 27 2021 vcsa4
crw-rw---- 1 root tty 7, 133 May 27 2021 vcsa5
crw-rw---- 1 root tty 7, 134 May 27 2021 vcsa6
drwxr-xr-x 2 root root 60 May 27 2021 vfio
crw------- 1 root root 10, 63 May 27 2021 vga_arbiter
crw------- 1 root root 10, 238 May 27 2021 vhost-net
crw------- 1 root root 10, 58 May 27 2021 vmci
crw------- 1 root root 10, 57 May 27 2021 vsock
crw-rw-rw- 1 root root 1, 5 May 27 2021 zero




SYS 系统目录

sysfs 虚拟文件系统提供了一种比 proc 更为理想的访问内核数据的途径。sysfs 文件系统总是被挂载在 /sys 挂载点上。

sysfs 与 proc 相比有很多优点,最重要的莫过于设计上的清晰。一个 proc 虚拟文件可能有内部格式,如 /proc/scsi/scsi ,它是可读可写的,并且读写格式不一样,代表不同的操作,应用程序中读到了这个文件的内容一般还需要进行字符串解析,而在写入时需要先用字符串格式化按指定的格式写入字符串进行操作。
相比而言,sysfs 的设计原则是一个属性文件只做一件事情,sysfs属性文件一般只有一个值,直接读取或写入。

SYS 系统目录结构

/sys下的目录结构是经过精心设计的:在 /sys/devices 下是所有设备的真实对象,包括如视频卡和以太网卡等真实的设备,也包括 ACPI 等不那么显而易见的真实设备、还有 tty, bonding 等纯粹虚拟的设备;在其它目录如 class, bus 等中则在分类的目录中含有大量对 devices 中真实对象引用的符号链接文件。
/sys/devices这是内核对系统中所有设备的分层次表达模型,也是 /sys 文件系统管理设备的最重要的目录结构
/sys/dev这个目录下维护一个按字符设备和块设备的主次号码(major:minor)链接到真实的设备(/sys/devices下)的符号链接文件,它是在内核 2.6.26 首次引入;
/sys/bus这是内核设备按总线类型分层放置的目录结构,devices 中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分;
/sys/class这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在 /sys/class/input 之下,而不论它们是以何种总线连接到系统。它也是构成 Linux 统一设备模型的一部分;
/sys/block这里是系统中当前所有的块设备所在,按照功能来说放置在 /sys/class 之下会更合适,在 2.6.26 内核中已正式移到 /sys/class/block
/sys/firmware这里是系统加载固件机制的对用户空间的接口,关于固件有专用于固件加载的一套API
/sys/fs这里按照设计是用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点,但目前只有 fuse,gfs2 等少数文件系统支持 sysfs 接口,一些传统的虚拟文件系统(VFS)层次控制参数仍然在 sysctl (/proc/sys/fs) 接口中中;
/sys/kernel这里是内核所有可调整参数的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的 slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于 sysctl (/proc/sys/kernel) 接口中
/sys/module这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在 /sys/module 中
/sys/power这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重启等。
/sys/slab(内核2.6.24 以后移至 /sys/kernel/slab)SLAB 内存分配器的实现


       
  

      

    Linux的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,称为设备文件。应用程序可以打开、关闭和读写这些设备文件,完成对设备的操作,就像操作普通的数据文件一样。为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号,如硬盘的主设备号是3。 一个字符设备或者块设备都有一个主设备号和次设备号。主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各设备。 

    Linux为所有的设备文件都提供了统一的操作函数接口,方法是使用数据结构struct file_operations。这个数据结构中包括许多操作函数的指针,如open()、close()、read()和write()等,但由于外设 的种类较多,操作方式各不相同。Struct file_operations结构体中的成员为一系列的接口函数,如用于读/写的read/write函数和用于控制的ioctl等。打开一个文件就是 调用这个文件file_operations中的open操作。不同类型的文l件有不同的file_operations成员函数,如普通的磁盘数据文件, 接口函数完成磁盘数据块读写操作;而对于各种设备文件,则最终调用各自驱动程序中的I/O函数进行具体设备的操作。这样,应用程序根本不必考虑操作的是设 备还是普通文件,可一律当作文件处理,具有非常清晰统一的I/O接口。所以file_operations是文件层次的I/O接口。

 内核中如何标识设备号

设备号是在驱动module中分配并注册的,而/dev目录下的设备文件是根据这个设备号创建的,因此,当访问/dev目录下的设备文件时,驱动module就知道,自己该出场服务了(当然是由内核通知)。在Linux内核看来,主设备号标识设备对应的驱动程序,告诉Linux内核使用哪一个驱动程序为该设备(也就是/dev下的设备文件)服务;而次设备号则用来标识具体且唯一的某个设备。在内核中,用dev_t类型(其实就是一个32位的无符号整数)的变量来保存设备的主次设备号,其中高12位表示主设备号,低20位表示次设备号。

设备获得主次设备号有两种方式:一种是手动给定一个32位数,并将它与设备联系起来(即用某个函数注册);另一种是调用系统函数给设备动态分配一个主次设备号。

     对于手动给定一个主次设备号,使用以下函数:
     int register_chrdev_region(dev_t first, 
     unsigned int -count, 
     char *name)
     其中first是我们手动给定的设备号,count是所请求的连续设备号的个数,而name是和该设备号范围关联的设备名称,它将出现在/proc/devices和sysfs中。
比如,若first为0x3FFFF0,count为0x5,那么该函数就会为5个设备注册设备号,分别是0x3FFFF0、 0x3FFFF1、 0x3FFFF2、 0x3FFFF3、 0x3FFFF4,其中0x3(高12位)为这5个设备所共有的主设备号(也就是说这5个设备都使用同一个驱动程序)。而0xFFFF0、 0xFFFF1、 0xFFFF2、 0xFFFF3、 0xFFFF4就分别是这5个设备的次设备号了。需要注意的是,若count的值太大了,那么所请求的设备号范围可能会和下一个主设备号重叠。比如若 first还是为0x3FFFF0,而count为0x11,那么first+count=0x400001,也就是说为最后两个设备分配的主设备号已经不是0x3,而是0x4了!用这种方法注册设备号有一个缺点,那就是若该驱动module被其他人广泛使用,那么无法保证注册的设备号是其他人的 Linux系统中未分配使用的设备号。

 与主次设备号相关的3个宏:

MAJOR(dev_t dev):根据设备号dev获得主设备号;
MINOR(dev_t dev):根据设备号dev获得次设备号;
MKDEV(int major, int minor):根据主设备号major和次设备号minor构建设备号