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下建立一個塊設備文件,而且分配主設備號與次設備號
● 塊設備文件是鏈接用戶空間和內核空間的橋樑,應用程序經過它可以找到在內核中的設備驅動,從而實現對設備的讀寫
至此,本文結束 在下才疏學淺,有撒湯漏水的,請各位不吝賜教...