web-dev-qa-db-ja.com

Ctrl + Alt + F <Num>を押すとどうなりますか?

現在の端末を変更するためにこのキーの組み合わせが押されたときにLinuxで何が起こるかについての説明を探しています。特に、このキーの組み合わせを傍受して端末を変更するソフトウェアコンポーネントは何ですか?カーネルですか?カーネルの場合、これを処理するソースファイルの場所を指定できますか?

編集:これがグラフィカル(X11)とテキストベースの両方の環境でどのように機能するかを理解したいと思います。

38
user31765

カーネルです。キーボードはハードウェアであり、そこで発生するすべてのことがカーネルを通過することに注意してください。 VT切り替えの場合、イベントはそれ自体で完全に処理され、ユーザースペースには何も渡されません(ただし、iospace関連の方法があり、ユーザースペースプログラムがスイッチの発生を通知して、それに影響を与える可能性があるため、 Xは間違いなく)。

カーネルにはkeymapビルドが組み込まれています。これは、loadkeysで実行中に変更でき、dumpkeysで表示できます。

_[...]
keycode  59 = F1               F13              Console_13       F25             
        alt     keycode  59 = Console_1       
        control alt     keycode  59 = Console_1       
keycode  60 = F2               F14              Console_14       F26             
        alt     keycode  60 = Console_2       
        control alt     keycode  60 = Console_2       
keycode  61 = F3               F15              Console_15       F27             
        alt     keycode  61 = Console_3       
        control alt     keycode  61 = Console_3
[...]   
_

カーネルソースには、このように見えるデフォルトのキーマップファイルが含まれています。 3.12.2では _src/drivers/tty/vt/defkeymap.map_ です。また、対応するdefkeymap.cファイルがあることにも気づくでしょう(これは_loadkeys --mktable_で生成できます)。処理は _keyboard.c_ (これらのファイルはすべて同じディレクトリにあります)にあり、 set_console() from _vt.c_ を呼び出します。

_» grep set_console *.c
keyboard.c:     set_console(last_console);
keyboard.c:     set_console(i);
keyboard.c:     set_console(i);
keyboard.c:     set_console(value);
vt.c:int set_console(int nr)
vt_ioctl.c:                     set_console(arg);
_

そのリストからいくつかのヒットを編集しました。最後の2行目で関数のシグネチャを確認できます。

したがって、これらは切り替えに関係するものです。呼び出しのシーケンスを見ると、最終的には_keyboard.c_の kbd_event() に戻ります。これは、モジュールのイベントハンドラーとして登録されます。

(3.12.2 _drivers/tty/vt/keyboard.c_ 1473行目)

_MODULE_DEVICE_TABLE(input, kbd_ids);

static struct input_handler kbd_handler = {
    .event      = kbd_event,   <--- function pointer HERE
    .match      = kbd_match,
    .connect    = kbd_connect,
    .disconnect = kbd_disconnect,
    .start      = kbd_start,
    .name       = "kbd",
    .id_table   = kbd_ids,
};  

int __init kbd_init(void)
{

[...]

    error = input_register_handler(&kbd_handler);           
_

したがって、kbd_event()は、実際のハードウェアドライバーから何かがバブルアップしたときに呼び出される必要があります(おそらく_drivers/hid/_または_drivers/input/_からの何か)。ただし、関数ポインターを介して登録されるため、そのファイルの外では_kbd_event_と呼ばれることはありません。

カーネルを精査するためのリソース

  • Linux相互参照識別子検索 は優れたツールです。
  • インタラクティブLinuxカーネルマップ は、相互参照ツールの興味深いグラフィカルフロントエンドです。
  • 大規模なLinuxカーネルメーリングリスト(LKML)のいくつかの歴史的なアーカイブがあり、少なくとも1995年までさかのぼります。それらのいくつかは維持されておらず、検索機能が壊れていますが、 gmane one は非常にうまく機能しているようです。人々はメーリングリストで多くの質問をしました、そしてそれは開発者の間のコミュニケーションの主要な手段でもあります。
  • トレースの簡単な手段として、独自のprintk行をソースに挿入できます(標準C libのすべてがstdioのprintfを含むカーネルコードで使用できるわけではありません)。 printkのものは、syslogに格納されます。

Wolfgang Mauererが2.6カーネルに関するすばらしい本を書きましたProfessional Linux Kernel Architecture。これは多くのソースを網羅しています。 Greg Kroah-Hartman は、過去10年間の主な開発者の1人であり、さまざまなことが行われています。

36
goldilocks