控制檯驅動¶
Linux 核心有兩種通用型別的控制檯驅動。第一種型別在引導過程中由核心分配給所有虛擬控制檯。這種型別將被稱為“系統驅動”,並且只允許存在一個系統驅動。系統驅動是持久的,它永遠不能被解除安裝,儘管它可能會變為非活動狀態。
第二種型別必須顯式載入和解除安裝。本文件將其稱為“模組化驅動”。多個模組化驅動可以隨時共存,每個驅動與其他驅動(包括系統驅動)共享控制檯。但是,模組化驅動不能接管當前被另一個模組化驅動佔用的控制檯。(例外:呼叫 do_take_over_console() 的驅動無論佔用控制檯的驅動型別如何,都將成功接管。)它們只能接管被系統驅動佔用的控制檯。同樣,如果模組化驅動被控制檯釋放,系統驅動將接管。
從程式設計師的角度來看,模組化驅動必須呼叫
do_take_over_console() - load and bind driver to console layer
give_up_console() - unload driver; it will only work if driver
is fully unbound
在較新的核心中,以下也可用
do_register_con_driver()
do_unregister_con_driver()
如果 sysfs 已啟用,可以檢查 /sys/class/vtconsole 的內容。這顯示了系統當前註冊的控制檯後端,其命名為 vtcon<n>,其中 <n> 是 0 到 15 的整數。因此
ls /sys/class/vtconsole
. .. vtcon0 vtcon1
/sys/class/vtconsole 中的每個目錄都有 3 個檔案
ls /sys/class/vtconsole/vtcon0
. .. bind name uevent
這些檔案代表什麼?
bind - 這是一個讀/寫檔案。讀取時顯示驅動狀態,寫入時用於將驅動繫結或解除繫結到虛擬控制檯。可能的值為
- 0
表示驅動未繫結,如果執行 echo 命令,則指示驅動解除繫結
- 1
表示驅動已繫結,如果執行 echo 命令,則指示驅動進行繫結
name - 只讀檔案。以這種格式顯示驅動名稱
cat /sys/class/vtconsole/vtcon0/name (S) VGA+ '(S)' stands for a (S)ystem driver, i.e., it cannot be directly commanded to bind or unbind 'VGA+' is the name of the driver cat /sys/class/vtconsole/vtcon1/name (M) frame buffer device In this case, '(M)' stands for a (M)odular driver, one that can be directly commanded to bind or unbind.uevent - 忽略此檔案
解除繫結時,模組化驅動首先被分離,然後系統驅動接管該驅動騰出的控制檯。另一方面,繫結操作會將驅動繫結到當前被系統驅動佔用的控制檯。
- 注意1
繫結和解除繫結必須在 Kconfig 中選擇。它位於
Device Drivers -> Character devices -> Support for binding and unbinding console drivers- 注意2
如果任何虛擬控制檯處於 KD_GRAPHICS 模式,則繫結或解除繫結將不會成功。將控制檯設定為 KD_GRAPHICS 的應用程式示例是 X。
此功能有多大用處?這對控制檯驅動開發者非常有用。透過將驅動從控制檯層解除繫結,可以解除安裝驅動、進行更改、重新編譯、重新載入並重新繫結驅動,而無需重新啟動核心。對於可能希望從幀緩衝控制檯切換到 VGA 控制檯,反之亦然的普通使用者,此功能也使其成為可能。(注意注意注意:請閱讀 Documentation/fb 下的 fbcon.txt 以獲取更多詳細資訊。)
開發者須知¶
do_take_over_console() 現已分解為
do_register_con_driver()
do_bind_con_driver() - private function
give_up_console() 是 do_unregister_con_driver() 的一個封裝,並且驅動必須完全解除繫結才能使此呼叫成功。con_is_bound() 將檢查驅動是否已繫結。
控制檯驅動編寫者指南¶
為了使繫結和解除繫結控制檯功能正常工作,控制檯驅動必須遵循以下準則
所有驅動(系統驅動除外)都必須呼叫 do_register_con_driver() 或 do_take_over_console()。do_register_con_driver() 只會將驅動新增到控制檯的內部列表。它不會接管控制檯。do_take_over_console(),顧名思義,也將接管(或繫結到)控制檯。
所有在
con->con_init()期間分配的資源都必須在con->con_deinit()中釋放。所有在
con->con_startup()中分配的資源都必須在驅動(之前已繫結)解除繫結時釋放。控制檯層沒有與con->con_startup()互補的呼叫,因此由驅動檢查何時可以合法釋放這些資源。在con->con_deinit()中呼叫con_is_bound()會有所幫助。如果呼叫返回false(),則可以安全地釋放資源。必須確保這種平衡,因為當重新繫結驅動到控制檯的請求到達時,con->con_startup()可能會再次被呼叫。驅動退出時,請確保驅動完全解除繫結。如果滿足條件,驅動必須呼叫
do_unregister_con_driver()或give_up_console()。do_unregister_con_driver()也可以在驅動無法服務控制檯請求的條件下呼叫。這可能發生在突然失去所有驅動的幀緩衝控制檯上。
當前的控制檯驅動應該仍然可以正常工作,但繫結和解除繫結它們可能會導致問題。透過最少的修復,這些驅動可以正常工作。
Antonino Daplas <adaplas@pol.net>