Linux上的配备

1. Linux 上的设施 (device)

Linux 操作系统中,各类装备驱动(device driver)通过设备控制器(device
controller)来治本各类设备(device),其涉嫌如下图所示:

机械设备 1

这个设施之中,

  • 受同一个 device driver 管理的设施都有一样的 major
    number,那么些数字可以看做设备的品种号码,被基本用于识别一类设施
  • 受同一个 device driver 管理的同一类设备中的每一个装置都有不同的
    minor number,这多少个数字可以看作设备编号,被装备驱动用来鉴别每个设备

设施驱动首要有三大类:

  • 面向包的网络设施驱动(package oriented network device driver)
  • 面向块的存储设备驱动(block oriented storage device
    driver),提供缓冲式(buffered)的配备访问。
  • 面向字节的字符设备驱动 (byte oriented char device
    driver),有时也称为裸设备(raw
    devices),提供非缓冲的直接的设施访问(unbuffered direct
    access),比如串口设备,录像头,声音设备等。实际上,除了网络设施和存储设备以外的任何设备都是某种字符设备。

除此以外,还有一类设备,称为伪设备(pseudo
device),它们是软件设施。Linux 上的 device 不肯定要有硬件装备,比如
/dev/null, /dev/zero 等。

至于字符设备和块设备的更多区别:

  • 块设备只好以块为单位接受输入和重临输出,而字符设备则以字节为单位。大多数配备是字符设备,因为它们不需要缓冲而且不以固定块大小举行操作。
  • 块设备对于I/O
    请求有相应的缓冲区,因而它们得以选用以什么顺序举行响应,字符设备无须缓冲且被一直读写。对于存储设备而言调
    读写的依次效率巨大,因为在读写连续的扇区比分此外扇区更快。
  • 字符设备只好被逐个读写,而块设备可以任意访问。尽管块设备可任意走访,然则对于磁盘这类机械设备而言,顺序地公司块设备的访问可以增强性能。

用户空间的各类应用是经过 device driver 来操作设备的:

机械设备 2

如果再详尽一些就是这般的:

机械设备 3图片来源于

从这多少个图上得以看看:

  • 机械设备,网络设施驱动之上,分别有包调度器(packet
    scheduler),网络协议层(network protocols),NetFilter (防火墙)和
    scoket 层,其中,网络设施驱动以 socket 作为应用层的接口
  • 块设备驱动之上,分别有 I/O Scheduler,通用块层(generic block
    layer)和文件系统,其中,块设备驱动以设备文件 (device
    file)作为应用层的受访者问口
  • 字符设备驱动之上,分别有 Line discipline 和
    terminals,其中,terminals 作为和采纳的拜访接口

Linux 系统中“一切皆文件”。每个设备,在 /dev
目录中都有对一个配备文件(device file),比如 /dev/sda 表示第一个SCSI/IDE 盘,/dev/vda 表示第一个 virtio
磁盘。应用程序通过走访这多少个设施文件像操作文件一律来拜访那一个设备,可以动用的接口包括:

  • int open(const char *path, int oflag, … )
  • int close(int fd);
  • ssize_t write(int fd, const void *buf, size_t nbyte)
  • ssize_t read(int fd, void *buf, size_t nbyte)
  • int ioctl(int d, int request, …)

在 Linux 系统上,设备驱动可以被动态加载和删除

  • lsmod – 列出当前早已被加载的模块
  • insmod <module_file> – insert/load 指定的模块文件
  • modprobe <module> – insert/load 指定的 module,以及所有倚重
  • rmmod <module> – remove/unload 指定的module

2. Linux 设备的 major 和 minor number

2.1 用 ls 获取

上文谈到了 major 和 number。简单地,可以从 ls 命令的出口中看出 device
的这几个numbers:

root@controller:/home/sammy# cd /dev
root@controller:/dev# ls -l
total 0
crw------- 1 root root     10, 175 Jul 18 15:24 agpgart
crw------- 1 root root     10, 235 Jul 18 15:24 autofs
brw-rw---- 1 root disk      7,   5 Jul 18 15:24 loop5
brw-rw---- 1 root disk      7,   6 Jul 18 15:24 loop6
brw-rw---- 1 root disk      8,   0 Jul 18 15:24 sda
brw-rw---- 1 root disk      8,   1 Jul 18 15:24 sda1
brw-rw---- 1 root disk      8,   2 Jul 18 15:24 sda2
brw-rw---- 1 root disk      8,   5 Jul 18 15:24 sda5
crw--w---- 1 root tty       4,  10 Jul 18 15:24 tty10
crw--w---- 1 root tty       4,  11 Jul 18 15:24 tty11
  • 以  ‘c’ 先导的一条龙表示该设施是一个字符设备,以 ‘b’
    先河的行表示这是一个块设备。
  • 10,175 这多个数字中,前面的 10 表示 major number,后边的 175 表示
    minor number。

2.2 major 和 minor 值的装置

野史上,设备的 major number
接纳的是注册制,各配备厂家在 http://www.lanana.org/
中注册他们的装置所利用的 major number。从
http://www.lanana.org/docs/device-list/devices-2.6+.txt 中还足以看出来
linux 2.6 内核中所分配的静态major numbers。

而是,现在,这些注册网站已经没有人珍爱了,取而代之的是动态分配制度。分配者是linux
内核的 udev 模块。它将确保在本系统中,<major number>:<minor
number>的结合是绝无仅有的,而在这多少个范围之外,它不会确保其惟一性。一旦分配好了后,你就可以从
/proc/device 文件中读出所分配的 major numbers,比如:

 2 pty
 3 ttyp
 4 ttyS
 6 lp
 7 vcs
 10 misc
 13 input
 14 sound
 21 sg
180 usbBlock devices:
 2 fd
 8 sd
 11 sr
 65 sd
 66 sd

3. 基于 major 和 minior numbers 识别磁盘类型

3.1 识别过程

据悉以下步骤来识别磁盘类型:

(1)使用 stat 命令获取装备文件的 major 和 minor
numbers。注意结果是16进制。

root@u1:/dev# stat -c %T /dev/vda #minor number
0
root@u1:/dev# stat -c %T /dev/vdb
10
root@u1:/dev# stat -c %T /dev/sda
0
root@u1:/dev# stat -c %t /dev/vda #major number
fd
root@u1:/dev# stat -c %t /dev/vdb
fd
root@u1:/dev# stat -c %t /dev/sda
8

(2)将16进制数字转化为10进制,并拼接字符串 /sys/dev/block/$decmajor:$minor/device/driver

/sys/dev/block/253:0/device/driver
/sys/dev/block/253:16/device/driver
/sys/dev/block/8:0/device/driver

(3)调用 readlink -f 命令,获取 device driver

root@u1:/dev# readlink -f /sys/dev/block/253:0/device/driver
/sys/bus/virtio/drivers/virtio_blk

root@u1:/dev# readlink -f /sys/dev/block/253:16/device/driver
/sys/bus/virtio/drivers/virtio_blk

root@u1:/dev# readlink -f /sys/dev/block/8:0/device/driver
/sys/bus/scsi/drivers/sd

从输出可以观望,/dev/vda 和 /dev/vdb 都是 virtio-block 类型的配备,而
/dev/sda 是 sd 即 SCSI 类型的装备。 

普遍的命名:

  • fd:软驱
  • hd:IDE 磁盘
  • sd:SCSI 磁盘
  • tty:terminals
  • vd:virtio 磁盘

 3.2 virtio block driver 的实现

virtio-blk
驱动的贯彻代码在 https://github.com/spotify/linux/blob/master/drivers/block/virtio_blk.c。从中可以寓目major 和 minor number 分配,以及配备命名的不二法门。

(1)设备命名形式

if (index < 26) {
        sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
    } else if (index < (26 + 1) * 26) {
        sprintf(vblk->disk->disk_name, "vd%c%c",
            'a' + index / 26 - 1, 'a' + index % 26);
    } else {
        const unsigned int m1 = (index / 26 - 1) / 26 - 1;
        const unsigned int m2 = (index / 26 - 1) % 26;
        const unsigned int m3 =  index % 26;
        sprintf(vblk->disk->disk_name, "vd%c%c%c",
            'a' + m1, 'a' + m2, 'a' + m3);
    }

可见:

  • virtio-blk 设备的称呼以 ‘vd’ 起始。从  ‘vda’ 开首递增,数目在 26
    个以内时,增长至 ‘vdz’;假设超越 26,则从 ’vdaa‘ 从来加强至
    ’vdzz‘;最高可以增长到 ’vdzzz‘。
  • 名称在装备被加载后被确定,在再次加载或者系统重启后会重新生成,因而对同一个装置其名称或者会发生变化。我的另一篇小说 精通QEMU/KVM 和
    Ceph(3):存储卷挂接和设备名称
    谈到了这种变动导致的题目。

(2)major number 是透过想根本注册获取的

static int __init init(void)
{
    major = register_blkdev(0, "virtblk");
    if (major < 0)
        return major;
    return register_virtio_driver(&virtio_blk);
}

register_blkdev
那一个艺术是水源系统调用,用于注册一个块设备,需要指定主设备号。假使指定的设备号为0,则会由系统活动分配一个。该措施调用之后,就足以在/proc/devices文件中看出该块设备以及它的
major number。

(3)minor number 是由装备的 index (索引)转化而来的

vblk->disk->first_minor = index_to_minor(index);

 

 

参照链接:

发表评论

电子邮件地址不会被公开。 必填项已用*标注