私は現在、Linuxカーネルとオペレーティングシステム全体について学んでおり、IRQ、ドライバ、スケジューリング、その他の重要なオペレーティングシステムの概念とキーボード関連リソースに関する優れたリソースをたくさん見つけました。 Linuxカーネルがキーボードのボタン押しを処理する方法の概要です。この段階では、すべての詳細を理解しようとするのではなく、概念をある程度包括的にリンクしようとしています。
次のシナリオが浮かび上がります。
- 私は単一のプロセッサを持つx64システムを使用しています。
VIM
複数のプロセス、特にエディタ(Process #1
)とsayLibreOffice
()が実行されていますProcess #2
。- 私は中です - キーを
VIM
押します。a
ただし、現在実行中のプロセスProcess #2
(VIM
次にスケジュールされます)。
今、状況がこのようになると想像しています。
- キーボードは一連のステップを経て電気信号(USBプロトコルエンコーディング)を生成し、それをUSBケーブルで送信します。
- 信号はUSBコントローラによって処理され、
APIC
PCI-e(および他のコントローラ/バス?)を介して割り込みコントローラ()に送信されます。トリガープロセッサAPIC
。INT Pin
- プロセッサは要求を
Kernel Mode
切り替え、それをオフセット()として使用します。記述子を取得し、その記述子を使用して割り込みハンドラルーチンのアドレスを取得します。私が理解したように、この割り込みハンドラは最初にキーボードドライバによって登録されます。IRQ-Number
APIC
Interrupt Descriptor Table Register
IDTR
- 割り込みハンドラを呼び出します(この場合はキーボードハンドラ)。
これは私の主な質問につながります。割り込みハンドラルーチンは、どのメカニズムを介して押されたキーを正しいプロセス(Process #1
)に渡しますか?実際にそうしますか、それともchar-device
一度に1つのプロセスでしか読み取ることができるバッファ(通過可能?)に押したキーを記録しますか(現在は)「含む」到着するProcess #1
)?いつ理解できません。Process #1
受け取るキー。割り込みハンドラとしてデータをすぐに処理するかどうかスケジュールすぐに処理しますか、または次回スケジューラがスケジュールしたときに重要なデータを処理しますか?
- このハンドラが(
IRET
)を返すと、コンテキストは以前に実行されていたプロセス(Process #2
)に戻ります。
答え1
これまでの理解は正確でしたが、それに基づいて構築する複雑さのほとんどを見逃しています。カーネルでの処理は複数の階層で行われ、キーストロークはこれらの階層を介して「バブリング」されます。
USB通信プロトコル自体ははるかに複雑です。 USBの割り込みハンドラルーチンはそれを処理し、必要に応じて複数のフラグメントから完全なUSBパケットを組み立てます。
いわゆる話すキーを使うキー高圧ガス放電管(「Human Interface Device」)プロトコルはUSBの上に構築されています。したがって、子USBカーネル層は、メッセージ全体がUSB HIDイベントであることを検出し、それをカーネルのHID層に渡します。
HID層は、初期化中にデバイスに必要なHID記述子に基づいてこのイベントを解釈します。その後、イベントを入力レイヤーに渡します。単一のHIDイベントは複数の主要イベントを生成できます。
入力レイヤーはカーネルキーボードレイアウトテーブルを使用して、スキャンコード(キーボードのキー位置)をキーコード(たとえばA
)にマッピングし、それを解釈しますShift。Altこの解釈の結果は、/dev/input/event*
ユーザー空間プロセスを通じて使用できます。evtest
これらのイベントをリアルタイムで視聴するために使用できます。
ただし、処理はここでは終了しません。 Xサーバー(グラフィック担当)には、evdev
デバイスからイベントを読み取り、/dev/input/event*
それをマッピングする一般的なドライバがあります。再びxmodmap
2番目のキーボードレイアウトテーブルセットに基づいています(このキーボードレイアウトテーブルはXKBD拡張を部分的に使用し、XKBD拡張を完全に使用して表示できます)。これは、Xサーバーがカーネル入力層より前のバージョンで、最初はマウスとPS / 2キーを直接処理するドライバがあったためです。
その後、Xサーバーはキーボードイベントを含むメッセージをXクライアント(アプリケーション)に送信します。アプリを使用してこれらのメッセージを表示できますxev
。LibreOffice
このイベントは直接処理され、VIM
イベントを処理するanで実行されxterm
、(推測されましたが)再処理を追加して最後にVIM
viaに渡します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
このようなキーワードを残してください...