linux一切皆文件之塊設(shè)備文件(四)

一、知識準(zhǔn)備

1、在linux中,一切皆為文件,所有不同種類的類型都被抽象成文件(比如:塊設(shè)備,socket套接字,pipe隊列)
2、操作這些不同的類型就像操作文件一樣,比如增刪改查等
3、塊設(shè)備是將信息存儲在大小固定的塊中,每一個塊都有自己的地址,塊設(shè)備支持隨機訪問。典型的塊設(shè)備比如我們使用的硬盤


二、環(huán)境準(zhǔn)備

組件 版本
OS Ubuntu 16.04.4 LTS


三、主設(shè)備號(major)與次設(shè)備號(minor)

● 當(dāng)一塊磁盤被注冊到操作系統(tǒng)的時候,會被分配主設(shè)備號與次設(shè)備號
● 其中主設(shè)備號代表了該設(shè)備屬于的類型,次設(shè)備號代表了該設(shè)備在操作系統(tǒng)中的唯一標(biāo)識

主設(shè)備號

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的主設(shè)備號是8,代表了sda這塊磁盤是屬于8這個類型的,那8是什么類型的?

root@Bastion:~# grep 8 /proc/devices
108 ppp
128 ptm
248 pps
  8 sd

在/proc/devices告訴我們,8是屬于sd類型的,那sd又是啥意思?

打開 https://www.kernel.org/doc/Documentation/admin-guide/devices.txt

   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這個類型代表了塊設(shè)備,并且是SCSI 硬盤

次設(shè)備號

由于/dev/sda做了1個分區(qū)/dev/sda1,再加上原有的/dev/sda,操作系統(tǒng)內(nèi)核給二者打上了唯一的標(biāo)記:
8,0 代表了/dev/sda
8,1 代表了/dev/sda1

小結(jié)一下:
主設(shè)備號:代表著某一類型的設(shè)備,比如SCSI硬盤、虛擬硬盤、USB等等
次設(shè)備號:操作系統(tǒng)分配的整數(shù),與主設(shè)備號一起(major,minor),組成了該設(shè)備在操作系統(tǒng)當(dāng)中唯一的ID

四、塊設(shè)備文件

● 塊設(shè)備文件是連接用戶空間和內(nèi)核空間的橋梁,通過塊設(shè)備文件描述符,能夠找到內(nèi)核中的設(shè)備驅(qū)動程序
● 通過內(nèi)核中的驅(qū)動程序從而對該設(shè)備進行讀寫

   +----------------------+
   | user space           |
   |                      |
   |      +---------+     |
   |      | test.py |     |
   |      +---------+     |
   +----------------------+
               |
               |
          +----v----+
          |/dev/sda1|
          +----+----+
               |
               |(8,1)
               |
+---------------------------------------------
| kernel space |                             |
|              |                             |
|              v                             |
|        +-----+----+      +---------------+ |
|        | major:8  |      | device driver | |
|        +-----+----+      |               | |
|              |           +---------------+ |       +--------+
|              +---------->|  minor:1      |-------->| device |
|                          +---------------+ |       +--------+
|                          |               | |
|                          +---------------+ |
+--------------------------------------------+


五、測試

(a)首先虛擬一個塊設(shè)備文件

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

我們已經(jīng)虛擬出一個塊設(shè)備文件了,由于是通過losetup虛擬出來的,所以major號只能為7

下面將該塊設(shè)備格式化、掛載:

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

至此,我們擁有了一個塊設(shè)備,并且大小為100M

(b)測試腳本

準(zhǔn)備一個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,然后進行讀寫
● 由于腳本中是相對路徑,并且當(dāng)前目錄在/mnt下,/mnt相關(guān)聯(lián)的硬盤是/dev/device_test
● 進程通過/dev/device_test拿到了該設(shè)備的設(shè)備號(7,80)
● 通過設(shè)備號在內(nèi)存中找到對應(yīng)的設(shè)備驅(qū)動程序,然后通過設(shè)備驅(qū)動程序?qū)K設(shè)備進行讀寫
● 在塊設(shè)備上沒有發(fā)現(xiàn)test.log,首先創(chuàng)建一個,然后開始對該文件每秒寫入一句'hello world'


六、小結(jié)

● 當(dāng)塊設(shè)備掛載的時候,會先在操作系統(tǒng)的/dev下創(chuàng)建一個塊設(shè)備文件,并且分配主設(shè)備號與次設(shè)備號
● 塊設(shè)備文件是連接用戶空間和內(nèi)核空間的橋梁,應(yīng)用程序通過它能夠找到在內(nèi)核中的設(shè)備驅(qū)動,從而實現(xiàn)對設(shè)備的讀寫



至此,本文結(jié)束
在下才疏學(xué)淺,有撒湯漏水的,請各位不吝賜教...

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容