忍不住再次說一下unix的流機制。周末在家調試linux的終端驅動,發現linux并沒有按照unix流機制的建議來實作tty驅動,雖然我對windows核心了解不如對linux深刻,可是還是略知一二,windows的分層驅動模型倒是和unix流機制甚是相似,如出一轍。windows借鑒了unix的很多思想,或者說英雄所見略同,而linux卻是典型的實用主義者,根本不管什麼架構。
linux的tty驅動基本分為三層,一層在虛拟檔案系統vfs,另一層是線路規程(或者稱行規程),最下面一層是裝置驅動,了解了大體架構之後再看linux的具體實作,vfs層的基本就是一個file_operations,而線路規程則是一個tty_ldisc,而驅動則沒有統一的表示了,驅動層和線路規程有一個接口,那就是線路規程的receive_buf函數,或者在硬體中斷中,或者在軟中斷中,或者在工作隊列中等,驅動程式調用receive_buf函數将字元放入一個隊列,然後喚醒等待的睡眠程序,在receive_buf執行線路規程規定的鍵碼的解釋,最終睡眠在tty的vfs層read方法中繼而睡眠線上路規程的read中的程序被喚醒,取出字元;寫終端的過程也是這樣,vfs的write直接調用線路規程的write,然後資料就到了驅動,每個tty都直接綁定一個tty_driver,後者有一個tty_operations,線路規程的write就是調用了該tty_driver的write...這個過程不就是最原始的unix對tty的處理機制嗎?和流機制相去甚遠,在流機制中,vfs層往下調用,應該對下層是什麼一無所知,是線路規程還是一般的驅動程式,還是一系列的規程等等,這些都應該對vfs層完全透明,可是linux的tty驅動實作中,一切都好似寫死的,雖然一個線路規程可以透明地堆疊在另一個線路規程上,但是vfs層下卻隻能是一個線路規程,和最原始的unix實作一樣,unix的隊列是用clist(别指望在網上得到大量資訊,如果你搜尋clist,結果十有八九是mfc的)實作的,該clist機制是基于單獨字元的緩沖,是以取字元或者放字元隻能一個一個進行,linux的隊列也是這樣,隻是不用clist這個結構體了,unix操作clist開銷要比linux的更大一些,因為操作clist結構體要比linux如今使用的單一隊列更複雜。
看看unix後來的實作,特别是bsd的實作,流機制引導下的分層模型大行其道,具體參見我前面的文章《從檔案系統看系統架構》。unix原始的clist實作的tty驅動和linux的一些tty裝置驅動一樣,都是對輸入和輸出的不對稱處理,輸入可以直接輸出到驅動,而輸入卻涉及到了裝置的中斷,是以為了不使中斷更延遲,原始unix和linux的某些裝置驅動實作都安排了兩個輸入隊列,中斷程式首先将資料放入第一個隊列,然後中斷傳回,而後的程序上下文或者軟中斷中在将這些裸資料經過線路規程後加入第二個輸入隊列(linux的receive_buf)。
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271803