概念:在Linux系統中,所有設備都被映射成 【設備文件】 來處理,設備文件,應用程序可以像操作普通文件一樣對硬件設備進行操作。
一、設備類型
整理自:(相當不錯,建議有時間看下原文)
一般情況下,以 Linux 的設備可區分為 3 種基本設備類型:字符設備、塊設備, 網絡設備
一個字符設備或塊設備都在/dev目錄下對應一個設備文件。
linux用戶程序通過設備文件(或稱設備節點)來使用驅動程序操作字符設備和塊設備。
- 字符設備
-
是指只能一個字節一個字節讀寫的設備,不能隨機讀取設備內存中的某一數據,讀取數據需要按照先后數據。
字符設備是面向流的設備,常見的字符設備有鼠標、鍵盤、串口、控制台和LED設備等。
本控制台( /dev/console )和串口( /dev/ttyS0)是字符設備的例子, 因為它們很好地展現了流的抽象.
字符設備通過文件系統結點來存取, 例如 /dev/tty1 和 /dev/lp0.
在一個字符設備和一個普通文件之間唯一有關的不同就是, 你經常可以在普通文件中移來移去, 但是大部分字符設備僅僅是數據通道, 你只能順序存取.然而, 存在看起來象數據區的字符設備, 你可以在里面移來移去. 例如, frame grabber 經常這樣, 應用程序可以使用 mmap 或者 lseek 存取整個要求的圖像.
字符設備文件(類型為C):
備注:
細心的人,可能會發現設備文件是無文件大小的,取而代之的是兩個號碼:主設備號+此設備號(見下文)
- 塊設備
-
是指可以從設備的任意位置讀取一定長度數據的設備。塊設備包括硬盤、磁盤、U盤和SD卡等
如同字符設備, 塊設備通過位於 /dev 目錄的文件系統結點來存取.
一個塊設備(例如一個磁盤)應該是可以駐有一個文件系統的.
在大部分的 Unix 系統, 一個塊設備只能處理這樣的 I/O 操作, 傳送一個或多個長度經常是 512 字節( 或一個更大的 2 的冪的數 )的整塊.
Linux, 相反, 允許應用程序讀寫一個塊設備象一個字符設備一樣 -- 它允許一次傳送任意數目的字節. 結果就是, 塊和字符設備的區別僅僅在內核以及在內部管理數據的方式上, 並且因此在內核/驅動的軟件接口上不同. 如同一個字符設備, 每個塊設備都通過一個文件系統結點被存取的, 它們之間的區別對用戶是透明的. 塊驅動和字符驅動相比, 與內核的接口完全不同.
塊設備文件(類型為B):
- 網絡接口
-
任何網絡事務都通過一個接口來進行, 就是說, 一個能夠與其他主機交換數據的設備.
通常, 一個接口是一個硬件設備, 但是它也可能是一個純粹的軟件設備, 比如環回接口.
一個網絡接口負責發送和接收數據報文, 在內核網絡子系統的驅動下, 不必知道單個事務是如何映射到實際的被發送的報文上的.
很多網絡連接( 特別那些使用 TCP 的)是面向流的, 但是網絡設備卻常常設計成處理報文的發送和接收.
一個網絡驅動對單個連接一無所知; 它只處理報文.
既然不是一個面向流的設備, 一個網絡接口就不象 /dev/tty1 那么容易映射到文件系統的一個結點上.
Unix 提供的對接口的存取的方式仍然是通過分配一個名子給它們( 例如 eth0 ), 但是這個名子在文件系統中沒有對應的入口.
內核與網絡設備驅動間的通訊與字符和塊設備驅動所用的完全不同. 不用 於read 和 write, 而是由內核調用和報文傳遞相關的函數.
備注:linux文件類型還包括: 普通文件(-), 套接字文件(S), 鏈接文件(L),可見:《linux文件類型全解析》, 剩下還有其他:目錄(D), 資料傳輸檔案(FIFO, PIPE),
二、主設備號 與 次設備號
查看 主設備號 與 次設備號: ls -al /dev
查看當前已加載的設備驅動程序的主設備號: cat /proc/devices
第一列為主設備號,第二列為設備名
每個字符設備和塊設備都必須有主次設備號,主設備號相同的設備是同類設備(使用同一驅動程序)
區別是否同類設備,可以更好的對設備進行管理和優化,主要體現在:
系統可能包含幾個同樣類型的設備,由同一個設備驅動程序管理(不需要重復加載驅動到內核)
可以將同類設備合並起來,便於插入到內核的數據結構中進行管理
三、其他
參照:《Linux內核--設備文件命名(官方文檔)》, 《對於Linux內核tty設備的一點理解》
以下是在 Mac 系統中的一些小實驗:
tty
1. 打開兩個終端,都切換到 root
step1: 終端1:
#通過 tty 獲取 當前終端 的對應的文件地址:
root# tty
/dev/ttys001
#持續監控 ttys001 文件內容
root# tail -f /dev/ttys001
step2: 終端2:
root# echo 'hello /dev/ttys0001' > /dev/ttys001
step3: 終端1 輸出了一下內容:
hello /dev/ttys0001
2. ssh 到一台linux系統,都切換到 root
step1: 終端1:
#通過 tty 獲取 當前終端 的對應的文件地址:
root# tty
/dev/pts/0
#持續監控 ttys001 文件內容
root# tail -f /dev/pts/0
step2: 終端2:
echo 'hello /dev/pts/0' > /dev/pts/0
step3: 終端1 輸出了一下內容:
hello /dev/pts/0