Linuxカーネルはキーボードの押し方をどのように処理しますか?

Linuxカーネルはキーボードの押し方をどのように処理しますか?

私は現在、Linuxカーネルとオペレーティングシステム全体について学んでおり、IRQ、ドライバ、スケジューリング、その他の重要なオペレーティングシステムの概念とキーボード関連リソースに関する優れたリソースをたくさん見つけました。 Linuxカーネルがキーボードのボタン押しを処理する方法の概要です。この段階では、すべての詳細を理解しようとするのではなく、概念をある程度包括的にリンクしようとしています。

次のシナリオが浮かび上がります。

  1. 私は単一のプロセッサを持つx64システムを使用しています。
  2. VIM複数のプロセス、特にエディタ(Process #1)とsay LibreOffice()が実行されていますProcess #2
  3. 私は中です - キーをVIM押します。aただし、現在実行中のプロセスProcess #2VIM次にスケジュールされます)。

今、状況がこのようになると想像しています。

  1. キーボードは一連のステップを経て電気信号(USBプロトコルエンコーディング)を生成し、それをUSBケーブルで送信します。
  2. 信号はUSBコントローラによって処理され、APICPCI-e(および他のコントローラ/バス?)を介して割り込みコントローラ()に送信されます。トリガープロセッサAPICINT Pin
  3. プロセッサは要求をKernel Mode切り替え、それをオフセット()として使用します。記述子を取得し、その記述子を使用して割り込みハンドラルーチンのアドレスを取得します。私が理解したように、この割り込みハンドラは最初にキーボードドライバによって登録されます。IRQ-NumberAPICInterrupt Descriptor Table RegisterIDTR
  4. 割り込みハンドラを呼び出します(この場合はキーボードハンドラ)。

これは私の主な質問につながります。割り込みハンドラルーチンは、どのメカニズムを介して押されたキーを正しいプロセス(Process #1)に渡しますか?実際にそうしますか、それともchar-device一度に1つのプロセスでしか読み取ることができるバッファ(通過可能?)に押したキーを記録しますか(現在は)「含む」到着するProcess #1)?いつ理解できません。Process #1 受け取るキー。割り込みハンドラとしてデータをすぐに処理するかどうかスケジュールすぐに処理しますか、または次回スケジューラがスケジュールしたときに重要なデータを処理しますか?

  1. このハンドラが(IRET)を返すと、コンテキストは以前に実行されていたプロセス(Process #2)に戻ります。

答え1

これまでの理解は正確でしたが、それに基づいて構築する複雑さのほとんどを見逃しています。カーネルでの処理は複数の階層で行われ、キーストロークはこれらの階層を介して「バブリング」されます。

USB通信プロトコル自体ははるかに複雑です。 USBの割り込みハンドラルーチンはそれを処理し、必要に応じて複数のフラグメントから完全なUSBパケットを組み立てます。

いわゆる話すキーを使うキー高圧ガス放電管(「Human Interface Device」)プロトコルはUSBの上に構築されています。したがって、子USBカーネル層は、メッセージ全体がUSB HIDイベントであることを検出し、それをカーネルのHID層に渡します。

HID層は、初期化中にデバイスに必要なHID記述子に基づいてこのイベントを解釈します。その後、イベントを入力レイヤーに渡します。単一のHIDイベントは複数の主要イベントを生成できます。

入力レイヤーはカーネルキーボードレイアウトテーブルを使用して、スキャンコード(キーボードのキー位置)をキーコード(たとえばA)にマッピングし、それを解釈しますShiftAltこの解釈の結果は、/dev/input/event*ユーザー空間プロセスを通じて使用できます。evtestこれらのイベントをリアルタイムで視聴するために使用できます。

ただし、処理はここでは終了しません。 Xサーバー(グラフィック担当)には、evdevデバイスからイベントを読み取り、/dev/input/event*それをマッピングする一般的なドライバがあります。再びxmodmap2番目のキーボードレイアウトテーブルセットに基づいています(このキーボードレイアウトテーブルはXKBD拡張を部分的に使用し、XKBD拡張を完全に使用して表示できます)。これは、Xサーバーがカーネル入力層より前のバージョンで、最初はマウスとPS / 2キーを直接処理するドライバがあったためです。

その後、Xサーバーはキーボードイベントを含むメッセージをXクライアント(アプリケーション)に送信します。アプリを使用してこれらのメッセージを表示できますxevLibreOfficeこのイベントは直接処理され、VIMイベントを処理するanで実行されxterm、(推測されましたが)再処理を追加して最後にVIMviaに渡しますstdin

十分に複雑ですか?

答え2

押したキーをバッファに書き込みます(文字デバイスを介して利用可能ですか?)。

はい、そう言うべきです。

その後、(低レベル)コンソールからtty(仮想)、擬似ttyまでカスケード接続されます。キーストロークは、アクティブな「コンソール」に従って/ dev / tty1または/ dev / tty5に書き込まれます。

xtermから(ps axf出力):

  467 tty1     Ss     0:38  \_ -bash
 5820 tty1     S+     0:00      \_ xinit fvwm -- vt9
 5821 tty9     S<sl+  54:15          \_ /usr/lib/Xorg :0 vt9
 5831 tty1     S      0:00          \_ xterm -geometry +1+1 -n login fvwm
 5833 pts/0    Ss+    0:38              \_ fvwm
 ...
 ...
  773 pts/0    S      0:07                  \_ xterm
  775 pts/2    Ss+    0:00                  |   \_ bash
14452 pts/0    S      0:04                  \_ xterm
14454 pts/1    Ss     0:00                  |   \_ bash
14507 pts/1    S      0:00                  |       \_ xfontsel
31044 pts/1    R+     0:00                  |       \_ ps ax f
19549 pts/0    S      0:00                  \_ xterm
19551 pts/3    Ss+    0:00                      \_ bash

これは、Xorgがtty1からtty9で始まる方法とfvwm(ウィンドウマネージャ)とxterm(ターミナルエミュレータ)が/dev/pts/0を「インポートする」方法と、新しいシェルが/dev/pts/1、pts/2を取得する方法を示します。 pts/3等

pid 19551 pts / 3 bashプロセスを有効にしたかどうかに関係なくアドバイスを提供xtermウィンドウでキーを押すか、echo hello >/dev/pts/3/ dev / tty5などのコンソールvtでこれを行うと、文字が正しいプロセスに移動します。

man ps「プロセスステータスコード」の下に説明されています(まあ、リストされています):

S    interruptible sleep (waiting for an event to complete)
s    is a session leader    
+    is in the foreground process group

このようなキーワードを残してください...

関連情報