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

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下建立一個塊設備文件,而且分配主設備號與次設備號
● 塊設備文件是鏈接用戶空間和內核空間的橋樑,應用程序經過它可以找到在內核中的設備驅動,從而實現對設備的讀寫



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

相關文章
相關標籤/搜索