Linux 操做系統中,各類設備驅動(device driver)經過設備控制器(device controller)來管理各類設備(device),其關係以下圖所示:html
這些設備之中,linux
設備驅動主要有三大類:git
除此之外,還有一類設備,稱爲僞設備(pseudo device),它們是軟件設備。Linux 上的 device 不必定要有硬件設備,好比 /dev/null, /dev/zero 等。github
關於字符設備和塊設備的更多區別:網絡
用戶空間的各類應用是經過 device driver 來操做設備的:socket
若是再詳細一些就是這樣的:svg
(圖片來源)oop
從這個圖上能夠看出:性能
Linux 系統中「一切皆文件」。每一個設備,在 /dev 目錄中都有對一個設備文件(device file),好比 /dev/sda 表示第一個 SCSI/IDE 盤,/dev/vda 表示第一個 virtio 磁盤。應用程序經過訪問這些設備文件像操做文件同樣來訪問這些設備,可使用的接口包括:網站
在 Linux 系統上,設備驅動能夠被動態加載和刪除
上文談到了 major 和 number。簡單地,能夠從 ls 命令的輸出中看出 device 的這兩個numbers:
root@controller:/home/sammy# cd /dev root@controller:/dev# ls -l total 0 crw------- 1 root root 10, 175 Jul 18 15:24 agpgart crw------- 1 root root 10, 235 Jul 18 15:24 autofs brw-rw---- 1 root disk 7, 5 Jul 18 15:24 loop5 brw-rw---- 1 root disk 7, 6 Jul 18 15:24 loop6 brw-rw---- 1 root disk 8, 0 Jul 18 15:24 sda brw-rw---- 1 root disk 8, 1 Jul 18 15:24 sda1 brw-rw---- 1 root disk 8, 2 Jul 18 15:24 sda2 brw-rw---- 1 root disk 8, 5 Jul 18 15:24 sda5 crw--w---- 1 root tty 4, 10 Jul 18 15:24 tty10 crw--w---- 1 root tty 4, 11 Jul 18 15:24 tty11
歷史上,設備的 major number 採用的是註冊制,各設備廠家在 http://www.lanana.org/ 中註冊他們的設備所使用的 major number。從 http://www.lanana.org/docs/device-list/devices-2.6+.txt 中還能夠看出來 linux 2.6 內核中所分配的靜態major numbers。
可是,如今,這個註冊網站已經沒有人維護了,取而代之的是動態分配製度。分配者是linux 內核的 udev 模塊。它將保證在本系統中,<major number>:<minor number>的組合是惟一的,而在這個範圍以外,它不會保證其唯一性。一旦分配好了後,你就能夠從 /proc/device 文件中讀出所分配的 major numbers,好比:
2 pty 3 ttyp 4 ttyS 6 lp 7 vcs 10 misc 13 input 14 sound 21 sg 180 usbBlock devices: 2 fd 8 sd 11 sr 65 sd 66 sd
根據如下步驟來識別磁盤類型:
(1)使用 stat 命令獲取設備文件的 major 和 minor numbers。注意結果是16進制。
root@u1:/dev# stat -c %T /dev/vda #minor number 0 root@u1:/dev# stat -c %T /dev/vdb 10 root@u1:/dev# stat -c %T /dev/sda 0 root@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/sda 8
(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
root@u1:/dev# readlink -f /sys/dev/block/253:0/device/driver /sys/bus/virtio/drivers/virtio_blk
root@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
從輸出能夠看出,/dev/vda 和 /dev/vdb 都是 virtio-block 類型的設備,而 /dev/sda 是 sd 即 SCSI 類型的設備。
常見的命名:
virtio-blk 驅動的實現代碼在 https://github.com/spotify/linux/blob/master/drivers/block/virtio_blk.c。從中能夠看出 major 和 minor number 分配,以及設備命名的方法。
(1)設備命名方法
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); }
可見:
(2)major number 是經過向內核註冊來獲取的
static int __init init(void) { major = register_blkdev(0, "virtblk"); if (major < 0) return major; return register_virtio_driver(&virtio_blk); }
register_blkdev 這個方法是內核系統調用,用於註冊一個塊設備,須要指定主設備號。若是指定的設備號爲0,則會由系統自動分配一個。該方法調用以後,就能夠在/proc/devices文件中看到該塊設備以及它的 major number。
(3)minor number 是由設備的 index (索引)轉化而來的
vblk->disk->first_minor = index_to_minor(index);
參考連接: