1、知识准备
一、在linux中,一切皆为文件,全部不一样种类的类型都被抽象成文件(好比:块设备,socket套接字,pipe队列)
二、操做这些不一样的类型就像操做文件同样,好比增删改查等
三、块设备是将信息存储在大小固定的块中,每个块都有本身的地址,块设备支持随机访问。典型的块设备好比咱们使用的硬盘node
2、环境准备
组件 | 版本 |
---|---|
OS | Ubuntu 16.04.4 LTS |
3、主设备号(major)与次设备号(minor)
● 当一块磁盘被注册到操做系统的时候,会被分配主设备号与次设备号
● 其中主设备号表明了该设备属于的类型,次设备号表明了该设备在操做系统中的惟一标识python
主设备号
root@Bastion:~# ls -l /dev/sd* brw-rw---- 1 root disk 8, 0 9月 30 17:47 /dev/sda brw-rw---- 1 root disk 8, 1 9月 30 17:47 /dev/sda1
sda的主设备号是8,表明了sda这块磁盘是属于8这个类型的,那8是什么类型的?linux
root@Bastion:~# grep 8 /proc/devices 108 ppp 128 ptm 248 pps 8 sd
在/proc/devices告诉咱们,8是属于sd类型的,那sd又是啥意思?shell
打开 https://www.kernel.org/doc/Documentation/admin-guide/devices.txtsocket
8 block SCSI disk devices (0-15) 0 = /dev/sda First SCSI disk whole disk 16 = /dev/sdb Second SCSI disk whole disk 32 = /dev/sdc Third SCSI disk whole disk ... 240 = /dev/sdp Sixteenth SCSI disk whole disk Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on partitions is 15.
终于清楚的看到,8这个类型表明了块设备,而且是SCSI 硬盘ide
次设备号
因为/dev/sda作了1个分区/dev/sda1,再加上原有的/dev/sda,操做系统内核给两者打上了惟一的标记:
8,0
表明了/dev/sda
8,1
表明了/dev/sda1测试
小结一下:
主设备号:表明着某一类型的设备,好比SCSI硬盘、虚拟硬盘、USB等等
次设备号:操做系统分配的整数,与主设备号一块儿(major,minor),组成了该设备在操做系统当中惟一的IDui
4、块设备文件
● 块设备文件是链接用户空间和内核空间的桥梁,经过块设备文件描述符,可以找到内核中的设备驱动程序
● 经过内核中的驱动程序从而对该设备进行读写spa
+----------------------+ | user space | | | | +---------+ | | | test.py | | | +---------+ | +----------------------+ | | +----v----+ |/dev/sda1| +----+----+ | |(8,1) | +--------------------------------------------- | kernel space | | | | | | v | | +-----+----+ +---------------+ | | | major:8 | | device driver | | | +-----+----+ | | | | | +---------------+ | +--------+ | +---------->| minor:1 |-------->| device | | +---------------+ | +--------+ | | | | | +---------------+ | +--------------------------------------------+
5、测试
(a)首先虚拟一个块设备文件
root@Bastion:~# dd if=/dev/zero of=/tmp/device_test bs=1M count=100 100+0 records in 100+0 records out 104857600 bytes (105 MB, 100 MiB) copied, 0.0890014 s, 1.2 GB/s root@Bastion:~# mknod /dev/device_test b 7 80 root@Bastion:~# losetup /dev/device_test /tmp/device_test
咱们已经虚拟出一个块设备文件了,因为是经过losetup虚拟出来的,因此major号只能为7操作系统
下面将该块设备格式化、挂载:
root@Bastion:~# mkfs.ext4 /dev/device_test mke2fs 1.42.13 (17-May-2015) Discarding device blocks: done Creating filesystem with 102400 1k blocks and 25688 inodes Filesystem UUID: f38c24be-851b-41ff-8d55-4e692d5a4c83 Superblock backups stored on blocks: 8193, 24577, 40961, 57345, 73729 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done root@Bastion:~# mount /dev/device_test /mnt
root@Bastion:~# df -h | grep /mnt /dev/device_test 93M 1.6M 85M 2% /mnt root@Bastion:/mnt# ls -l /dev/device_test brw-r--r-- 1 root root 7, 80 Nov 12 09:54 /dev/device_test
至此,咱们拥有了一个块设备,而且大小为100M
(b)测试脚本
准备一个python文件,每秒往test.log写入hello world
root@Bastion:/mnt# more device_test.py import time f = open('test.log','a+') while 1: f.write('hello world\n') time.sleep(1)
运行并查看其打开的文件描述符
root@Bastion:/mnt# python device_test.py & [1] 25873 root@Bastion:/mnt# lsof -n | grep 25873 COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME ... python 25873 root 3u REG 7,80 8923 14 /mnt/test.log
整理一下咱们的信息:
● 首先运行脚本,它的进程号为25873。脚本的逻辑是须要打开test.log,而后进行读写
● 因为脚本中是相对路径,而且当前目录在/mnt下,/mnt
相关联的硬盘是/dev/device_test
● 进程经过/dev/device_test
拿到了该设备的设备号(7,80)
● 经过设备号在内存中找到对应的设备驱动程序,而后经过设备驱动程序对块设备进行读写
● 在块设备上没有发现test.log,首先建立一个,而后开始对该文件每秒写入一句'hello world'
6、小结
● 当块设备挂载的时候,会先在操做系统的/dev下建立一个块设备文件,而且分配主设备号与次设备号
● 块设备文件是链接用户空间和内核空间的桥梁,应用程序经过它可以找到在内核中的设备驱动,从而实现对设备的读写
至此,本文结束 在下才疏学浅,有撒汤漏水的,请各位不吝赐教...