linux 系统盘无法ls,识别 Linux上的设备(磁盘)类型

https://www.cnblogs.com/sammyliu/p/5729026.html

虚机上查看

wGun2KYLNA0lgAAAABJRU5ErkJggg==

1. Linux 上的设备 (device)

Linux 操作系统中,各种设备驱动(device driver)通过设备控制器(device controller)来管理各种设备(device),其关系如下图所示:

这些设备之中,

受同一个 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 来操作设备的:

如果再详细一些就是这样的:

从这个图上可以看出:

网络设备驱动之上,分别有包调度器(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 - insert/load 指定的模块文件

modprobe - insert/load 指定的 module,以及所有依赖

rmmod - remove/unload 指定的module

2. Linux 设备的 major 和 minor number

2.1 用 ls 获取

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

root@controller:/home/sammy# cd /dev

root@controller:/dev# ls -l

total0crw------- 1 root root 10, 175 Jul 18 15:24agpgart

crw------- 1 root root 10, 235 Jul 18 15:24autofs brw-rw---- 1 root disk 7, 5 Jul 18 15:24loop5

brw-rw---- 1 root disk 7, 6 Jul 18 15:24loop6

brw-rw---- 1 root disk 8, 0 Jul 18 15:24sda

brw-rw---- 1 root disk 8, 1 Jul 18 15:24sda1

brw-rw---- 1 root disk 8, 2 Jul 18 15:24sda2

brw-rw---- 1 root disk 8, 5 Jul 18 15:24sda5

crw--w---- 1 root tty 4, 10 Jul 18 15:24tty10

crw--w---- 1 root tty 4, 11 Jul 18 15:24 tty11

48304ba5e6f9fe08f3fa1abda7d326ab.png

以  'c' 开头的一行表示该设备是一个字符设备,以 'b' 开头的行表示这是一个块设备。

10,175 这两个数字中,前面的 10 表示 major number,后面的 175 表示 minor number。

2.2 major 和 minor 值的设置

历史上,设备的 major number 采用的是注册制,各设备厂家在  中注册他们的设备所使用的 major number。从 docs/device-list/devices-2.6+.txt 中还可以看出来 linux 2.6 内核中所分配的静态major numbers。

但是,现在,这个注册网站已经没有人维护了,取而代之的是动态分配制度。分配者是linux 内核的 udev

模块。它将保证在本系统中,:的组合是唯一的,而在这个范围之外,它不会保证其惟一性。一旦分配好了后,你就可以从 /proc/device

文件中读出所分配的 major numbers,比如:

48304ba5e6f9fe08f3fa1abda7d326ab.png

2pty3ttyp4ttyS6lp7vcs10misc13input14sound21sg180usbBlock devices:2fd8sd11sr65sd66 sd

48304ba5e6f9fe08f3fa1abda7d326ab.png

3. 根据 major 和 minior numbers 识别磁盘类型

3.1 识别过程

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

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

48304ba5e6f9fe08f3fa1abda7d326ab.png

root@u1:/dev# stat -c %T /dev/vda #minor number0root@u1:/dev# stat -c %T /dev/vdb10root@u1:/dev# stat -c %T /dev/sda0root@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/sda8

48304ba5e6f9fe08f3fa1abda7d326ab.png

(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

48304ba5e6f9fe08f3fa1abda7d326ab.png

root@u1:/dev# readlink -f /sys/dev/block/253:0/device/driver/sys/bus/virtio/drivers/virtio_blkroot@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

48304ba5e6f9fe08f3fa1abda7d326ab.png

从输出可以看出,/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 驱动的实现代码在 。从中可以看出 major 和 minor number 分配,以及设备命名的方法。

(1)设备命名方法

48304ba5e6f9fe08f3fa1abda7d326ab.png

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);

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

可见:

virtio-blk 设备的名称以 ‘vd’ 开头。从  ‘vda’ 开始递增,数目在 26 个以内时,增长至 ‘vdz’;如果超过 26,则从 ’vdaa‘ 一直增长至 ’vdzz‘;最高可以增长到 ’vdzzz‘。

名称在设备被加载后被确定,在重新加载或者系统重启后会重新生成,因此对同一个设备其名称可能会发生变化。我的另一篇文章 理解 QEMU/KVM 和 Ceph(3):存储卷挂接和设备名称 谈到了这种变化导致的问题。

(2)major number 是通过向内核注册来获取的

48304ba5e6f9fe08f3fa1abda7d326ab.png

static int __init init(void)

{

major= register_blkdev(0, "virtblk");if (major < 0)returnmajor;return register_virtio_driver(&virtio_blk);

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

register_blkdev 这个方法是内核系统调用,用于注册一个块设备,需要指定主设备号。如果指定的设备号为0,则会由系统自动分配一个。该方法调用之后,就可以在/proc/devices文件中看到该块设备以及它的 major number。

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值