操作系統設備驅動學習之旅——以顯示器驅動為例
從這一節開始,我要學習操作系統的第四個部分,就是i o設備的驅動。今天要講的是第26講,內容圍繞i o設備中的顯示器展開,探究顯示器是如何被驅動的,也就是操作系統怎樣讓用戶使用顯示器,最終會落腳到print f
這個函數是如何將內容顯示在屏幕上的。
設備驅動基礎原理
操作系統是管理計算機硬件的一層軟件。
之前,我已經學習了操作系統如何管理cpu,弄清楚了fork
以及進程管理的含義,明白了cpu是如何被抽象為進程的;也學習了內存管理相關知識,了解了內存如何分段、分頁,以及虛擬內存的引出,直到數據最終寫入物理內存。現在,我要開始學習計算機硬件中的另一重要部分——i o設備,這一講和下一講主要聚焦鍵盤和顯示器,之后還會涉及磁盤及基于磁盤抽象出的文件系統,但本質上都是i o設備的驅動。
在學習具體設備驅動前,得先明確計算機讓外設工作的原理。這是計算機的基本常識,使用外設時,每個外設都有對應的控制器,比如顯示器的顯卡。cpu只需向外設控制器中的寄存器或存儲區域發送一條指令,控制器就會依據指令內容操控硬件。以顯示器為例,cpu給顯卡寄存器發指令,顯卡就能讓顯示器顯示內容。通常,cpu發出指令后會去執行別的進程,等外設完成任務,會向cpu發送中斷信號,cpu再處理中斷,可能涉及數據傳輸等操作。
總結起來,操作系統讓外設工作的核心就兩點:一是向控制器發指令,最終表現為類似out
的指令;二是處理外設工作完成后的中斷。雖然實際操作外設的代碼很多,但核心指令就那么幾條。之所以有大量代碼,是為了讓外設使用更簡單,這就需要提供統一的視圖。因為不同設備的控制器不同,直接操作寄存器很麻煩,不同公司硬件設計也有差異,所以操作系統要形成統一接口,也就是文件視圖,這樣既能隱藏細節方便用戶,內部還能進行高效處理。
簡而言之,外設驅動主要做三件事:
- 發出
out
指令,操控設備控制器寄存器; - 進行設備中斷處理;
- 提供統一文件視圖,方便用戶使用。
print f
顯示原理探究
接下來,我通過print f
這個實際例子來深入理解設備驅動。print f
本質上是一段操作外設的程序,和其他設備操作一樣,遵循統一規則。在linux系統中,操作設備通常表現為open
、read
、write
,print f
也不例外,它打開的是顯示器對應的文件,然后進行寫入操作。操作系統為用戶提供統一的文件接口,通過不同的設備文件名區分操作的設備,print f
對應的設備文件名決定了它操作的是顯示器。
具體來看,print f
最終會變成系統調用write
,寫成write(1,buffer,...)
,這里的1
決定了數據輸出到顯示器,buffer
是格式化后的字符串緩沖區。系統調用通過int 0x80
進入內核,執行sys_write
。這里關鍵的1
是文件描述符,它來自當前進程pcb
數組的第一項,這個文件描述符對應一個文件,文件的inode
中存放著設備相關信息。
那么1
對應的文件是怎么來的呢?進程的pcb
是fork
創建時拷貝父進程的,所有進程打開文件的指針都源于父進程。系統初始化時,0
號進程創建相關進程,打開了一個文件并拷貝兩份,1
對應的文件就是dev/tty0
,tty
代表終端設備。open
系統調用會根據文件名讀入文件的inode
信息,操作系統依據這些信息決定后續操作路徑。
根據inode
信息判斷設備類型,如果是字符設備,就執行rw_char
,并根據設備號繼續分支。dev/tty0
是字符設備,設備號為4
,通過設備號在函數指針數組中找到對應的處理函數rw_ttyx
。因為是write
操作,所以會調用tty_write
函數,這個函數會將數據先寫入緩沖區right_q
。這涉及到緩沖技術,由于cpu和內存操作速度快,顯示器顯示速度慢,通過緩沖區可以平衡速度差異,緩沖區就像生產者 - 消費者模型中的共享緩沖區,寫滿時生產者(數據寫入操作)會睡眠等待,不滿時則寫入數據。
數據寫入緩沖區后,會調用函數從緩沖區取出數據輸出到顯示器。tty_write
函數會繼續調用console_write
,console
就是終端設備,即顯示器。console_write
函數會從緩沖區取出字符c
,通過out
指令將字符輸出到顯示器。具體的匯編指令會將字符屬性賦給ah
,字符賦給al
(ax
由ah
和al
組成),然后將ax
寫入顯存地址pose
。這里涉及內存和i o設備的編址方式,如果是統一編址用mov
指令,如果是獨立編址用out
指令,通常顯存較大,采用獨立編址,但本質上mov
和out
都是對i o設備控制器中的存儲區域進行寫操作。
總結與實驗展望
至此,我梳理清楚了print f
的整個過程。從系統調用write
開始,通過統一文件接口,依據設備信息逐步找到驅動顯示器的函數,利用緩沖技術和相關指令,最終將數據輸出到顯存顯示在屏幕上。設備驅動的核心就是cpu
向外設控制寄存器發指令進行讀寫,并形成統一文件視圖方便使用,同時處理中斷。相比cpu和內存管理,設備驅動相對簡單。
關于mov ax,pose
中的pose
,它每次寫完會加2
,因為顯存存儲字符和屬性各占一個字節。初始的pose
值在系統啟動時,通過setup
程序根據bios
中斷取出硬件參數(包括光標位置),將光標所在顯存位置存入90000
處,初始化時再將其賦值給pose
。