Linux-Kernel

Linux 核心中如何處理鍵盤按下?

  • April 13, 2020

我目前正在學習一般的 Linux 核心和作業系統,雖然我找到了很多關於 IRQ、驅動程序、調度和其他重要作業系統概念以及與鍵盤相關的資源的好資源,但我很難把它們放在一起Linux 核心如何處理鍵盤上的按鈕按下的全面概述。在這個階段,我並沒有試圖理解每一個細節,而是試圖將概念聯繫起來,有點全面。

我想到了以下場景:

  1. 我在一台帶有單個處理器的 x64 機器上。
  2. 有幾個程序正在執行,特別是 Editor VIM( Process #1) 和 say LibreOffice( Process #2)。
  3. 我在裡面VIM按-a鍵。但是,目前正在執行的程序是Process #2VIM下一個計劃)。

這就是我現在想像的事情:

  1. 鍵盤通過一系列步驟生成一個電信號(USB 協議編碼),然後將其發送到 USB 線。
  2. 信號由 USB 控制器處理,並通過 PCI-e(可能還有其他控制器/匯流排?)發送到中斷控制器(APIC)。處理器的APIC觸發器INT Pin
  3. 處理器切換到並從 中Kernel Mode請求一個,它用作( ) 的偏移量。獲得一個描述符,然後用於獲得中斷處理程序的地址。據我了解,這個中斷處理程序最初是由鍵盤驅動程序註冊的?IRQ-Number``APIC``Interrupt Descriptor Table Register``IDTR
  4. 呼叫中斷處理程序(在本例中為鍵盤處理程序)。

這讓我想到了我的主要問題:中斷處理程序常式通過哪種機制將按下的鍵傳達給正確的程序(Process #1)?它實際上是這樣做的,還是只是將按下的鍵寫入緩衝區(通過char-device? 可用),該緩衝區一次對一個程序只讀(並且目前*“附加”Process #1)?我不明白什麼時候Process #1 收到鑰匙。它會立即處理數據,因為中斷處理程序會立即調度*程序,還是會在調度程序下一次調度它時處理關鍵數據?

  1. 當此處理程序返回 ( IRET) 時,上下文切換回先前執行的程序 ( Process #2)。

到目前為止,您的理解是正確的,但是您錯過了基於此的大部分複雜性。核心中的處理髮生在幾個層中,並且按鍵通過這些層“冒泡”。

USB 通信協議本身涉及更多。USB 的中斷處理程序會處理這個問題,並在必要時從多個片段組裝一個完整的 USB 數據包。

按鍵使用所謂的HID(“人機介面設備”)協議,該協議建立在 USB 之上。所以較低的 USB 核心層檢測到完整的消息是一個 USB HID 事件,並將其傳遞給核心中的 HID 層。

HID 層根據它在初始化時要求設備提供的 HID 描述符來解釋此事件。然後它將事件傳遞給輸入層。單個 HID 事件可以生成多個按鍵事件。

輸入層使用核心鍵盤佈局表將掃描碼(鍵盤上鍵的位置)映射到鍵碼(如A)並解釋ShiftAlt等。這種解釋的結果可通過/dev/input/event*使用者態程序獲得。您可以使用evtest實時觀看這些事件。

但是這裡的處理還沒有結束。X 伺服器(負責圖形)有一個通用evdev驅動程序,它從設備讀取事件/dev/input/event*,然後根據第二組鍵盤佈局表再次xmodmap映射它們(您可以通過 XKBD 擴展部分和完全看到這些)。這是因為 X 伺服器早於核心輸入層,並且在早期有驅動程序直接處理滑鼠和 PS/2 鍵。

然後 X 伺服器向 X 客戶端(應用程序)發送一條包含鍵盤事件的消息。您可以使用應用程序查看這些消息xevLibreOffice將直接處理此事件,VIM將在xterm處理事件的 an 中執行,並且(您猜對了)再次對其添加一些額外的處理,最後將其傳遞給VIMvia stdin

夠複雜嗎?

引用自:https://unix.stackexchange.com/questions/545274