Linux 核心中如何處理鍵盤按下?
我目前正在學習一般的 Linux 核心和作業系統,雖然我找到了很多關於 IRQ、驅動程序、調度和其他重要作業系統概念以及與鍵盤相關的資源的好資源,但我很難把它們放在一起Linux 核心如何處理鍵盤上的按鈕按下的全面概述。在這個階段,我並沒有試圖理解每一個細節,而是試圖將概念聯繫起來,有點全面。
我想到了以下場景:
- 我在一台帶有單個處理器的 x64 機器上。
- 有幾個程序正在執行,特別是 Editor
VIM
(Process #1
) 和 sayLibreOffice
(Process #2
)。- 我在裡面
VIM
按-a
鍵。但是,目前正在執行的程序是Process #2
(VIM
下一個計劃)。這就是我現在想像的事情:
- 鍵盤通過一系列步驟生成一個電信號(USB 協議編碼),然後將其發送到 USB 線。
- 信號由 USB 控制器處理,並通過 PCI-e(可能還有其他控制器/匯流排?)發送到中斷控制器(
APIC
)。處理器的APIC
觸發器INT Pin
。- 處理器切換到並從 中
Kernel Mode
請求一個,它用作( ) 的偏移量。獲得一個描述符,然後用於獲得中斷處理程序的地址。據我了解,這個中斷處理程序最初是由鍵盤驅動程序註冊的?IRQ-Number``APIC``Interrupt Descriptor Table Register``IDTR
- 呼叫中斷處理程序(在本例中為鍵盤處理程序)。
這讓我想到了我的主要問題:中斷處理程序常式通過哪種機制將按下的鍵傳達給正確的程序(
Process #1
)?它實際上是這樣做的,還是只是將按下的鍵寫入緩衝區(通過char-device
? 可用),該緩衝區一次對一個程序只讀(並且目前*“附加”到Process #1
)?我不明白什麼時候Process #1
收到鑰匙。它會立即處理數據,因為中斷處理程序會立即調度*程序,還是會在調度程序下一次調度它時處理關鍵數據?
- 當此處理程序返回 (
IRET
) 時,上下文切換回先前執行的程序 (Process #2
)。
到目前為止,您的理解是正確的,但是您錯過了基於此的大部分複雜性。核心中的處理髮生在幾個層中,並且按鍵通過這些層“冒泡”。
USB 通信協議本身涉及更多。USB 的中斷處理程序會處理這個問題,並在必要時從多個片段組裝一個完整的 USB 數據包。
按鍵使用所謂的HID(“人機介面設備”)協議,該協議建立在 USB 之上。所以較低的 USB 核心層檢測到完整的消息是一個 USB HID 事件,並將其傳遞給核心中的 HID 層。
HID 層根據它在初始化時要求設備提供的 HID 描述符來解釋此事件。然後它將事件傳遞給輸入層。單個 HID 事件可以生成多個按鍵事件。
輸入層使用核心鍵盤佈局表將掃描碼(鍵盤上鍵的位置)映射到鍵碼(如
A
)並解釋Shift
、Alt
等。這種解釋的結果可通過/dev/input/event*
使用者態程序獲得。您可以使用evtest
實時觀看這些事件。但是這裡的處理還沒有結束。X 伺服器(負責圖形)有一個通用
evdev
驅動程序,它從設備讀取事件/dev/input/event*
,然後根據第二組鍵盤佈局表再次xmodmap
映射它們(您可以通過 XKBD 擴展部分和完全看到這些)。這是因為 X 伺服器早於核心輸入層,並且在早期有驅動程序直接處理滑鼠和 PS/2 鍵。然後 X 伺服器向 X 客戶端(應用程序)發送一條包含鍵盤事件的消息。您可以使用應用程序查看這些消息
xev
。LibreOffice
將直接處理此事件,VIM
將在xterm
處理事件的 an 中執行,並且(您猜對了)再次對其添加一些額外的處理,最後將其傳遞給VIM
viastdin
。夠複雜嗎?