web-dev-qa-db-ja.com

カーネルの実行でサポートされるシステムコール

現在実行中のLinuxカーネルでサポートされているシステムコールの数またはリストを取得する方法はありますか?したがって、実行中のカーネルのsyscallテーブルを「読み取る」方法を見つけたいと思います。

9
Swair

ファイル/proc/kallsymsには、実行中のカーネルのすべてのシンボルがリストされています。慣例により、システムコールの名前はsys_で始まります。 64ビットシステムでは、32ビットプログラムのシステムコールの名前はsys32_で始まります。厳密に言えば、これはシステムコールではなく内部カーネル関数をリストしますが、対応は機能すると思います(すべてのシステムコールは内部カーネル関数を呼び出してジョブを実行し、名前は常にsys_を使用したシステムコールの名前だと思います先頭に追加)。

</proc/kallsyms sed -n 's/.* sys_//p'

システムコールの変更は非常に遅いため、これは通常、有用な情報ではありません。オプションのコンポーネントは、デバイス(readwriteがそれを切り取らない場合 ioctl を使用)、ファイルシステム、ソケットなど。サポートされているシステムコールのリストを決定しても、システムがサポートしている機能については何もわかりません。他の内部関数名も非常に迅速に変更されるため、役に立ちません。あるカーネルバージョンで一部の機能を実装する関数の名前は、次のバージョンで変更される可能性があります。

TL; DR

私はこの回答を書いているときに新しい選択肢を見つけ続けたので、それぞれについて少し詳細を書いて、いくつかの統計を作成しました。基本的に、次のいずれかを実行できます。

  • Gillesの回答を読んでください。これは、クリーンで高速な方法を提供します(/procに依存します)。
  • ドキュメントリソースを使用してください。
  • システムのCヘッダーファイルを使用します。
  • カーネルソースコード自体を使用します。
  • /sysディレクトリを使用します。

計算を行った後、システムコールの数の点で最良の結果が得られると思われるため、(代替案の中でも)/sysファイルシステムを使用することをお勧めします。他のトリックについて読みたくない場合は、そのセクションに直接ジャンプできます。

ドキュメントリソースの使用

それらのいくつかを見逃すかもしれませんが、aproposを使用して、セクション2(システムコール)に属するすべてのマンページを一覧表示できます。

$ apropos -s2 . | awk '{print $1}' | column

派手な列化された出力が必要ない場合は、columnを削除してください。

私はそれを見つけたばかりですが、システムコールに関するLinuxのマニュアルページがあり、そのほとんどを見つけることができます。

$ man syscalls

私はまた興味深いかもしれないこれらの2つのウェブサイトに出くわしました:

ヘッダーファイルの使用

編集:さて、プログラムで(または少なくとも、文書化された機能に依存せずに)利用可能なシステムコールを決定することになると、カーネルはそのシステムコールのテーブルを保持していません。少なくとも、文字列のリストの形式ではありません(おそらくそれらを操作することを期待しています)。このレベルでは、関数名ではなく、関数のアドレスとポインターについて話します。

私は自分の/usr/includeディレクトリを参照して、いくつかのことをgrep- edしました。以下のディレクトリが興味深いかもしれません。それらのいくつかは、アーキテクチャとディストリビューションに応じて、マシン上で異なる場合がありますが、それらを適応させることができると確信しています。

  • / usr/include/linux
  • / usr/include/x86_64-linux-gnu
  • / usr/include/sys
  • / usr/include/asm-generic

このファイルで関数定義を探すと、完全には定義されていなくても、多くのシステムコールに出くわすでしょう。これらのディレクトリでいくつかのgrepsを実行しましたが、いくつかのシステムコールについての言及を見つけることができました。次に例を示します。

$ grep 'sys_exit' /usr/include -R
asm-generic/unistd.h:__SYSCALL(__NR_exit, sys_exit)

だから、それらのいくつかを見つける別の方法は次のようになると思います:

$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')'

カーネルのソースコードとそのsyscallテーブルを使用する

もう1つの解決策は、(ヘッダーだけでなく)カーネルソースコード自体を使用して、効率的に検索する方法を見つけることです。 カーネルコミット303395ac3bf3e2cb488435537d416bc840438fcb であるため、これは以前よりも少し簡単だと感じるかもしれません。以下は、3.13(私のカーネル)の例です。

$ wget https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/Arch/x86/syscalls/syscall_64.tbl?id=refs/tags/v3.13 -O syscall_64.tbl

実際のsyscallsテーブルを取得したので、それを参照するだけです。

$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl

unameArchを使用して、実行中にtblファイルを git.kernel.org から直接ダウンロードする方法を見つけることができます。カーネルのバージョンとアーキテクチャ。

/sysファイルシステムの使用

Gillesの答えは私に少しインスピレーションを与えました、そしてあなたはそれらのシステムコールを/sys/kernel/debug/tracing/events/syscallsの中に見つけるかもしれません。このディレクトリは、システムでの各システムコールの使用を監視するために使用されます。各syscallには2つのディレクトリがあります。

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

したがって、lsgrep、およびcut ..を使用します。

$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3

統計

私のシステムでは:

  • マニュアルページを使用すると、440のシステムコールが明らかになりました。
  • ヘッダーファイルの__SYSCALLgrep- ingにより、212のシステムコールが明らかになりました。
  • カーネルソースからsyscallsテーブルを読み取ると、346のシステムコールが明らかになりました。
  • /sysを使用すると、290のシステムコールが明らかになりました。

さて、すべてをまとめると...

$ apropos -s2 . | awk '{print $1}' > system_calls.txt
$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')' >> system_calls.txt
$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl >> system_calls.txt
$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3 >> system_calls.txt

$ sort < system_calls.txt | uniq | wc -l
707

707システムコールです。もちろん、この数は「システムコール」の非常に柔軟な定義を反映しています。 .13は274のシステムコールのみを提供することになっています/sysの読み取りが最も近いソリューションのようです)。

7
John WH Smith

すべての答えは結構です。

特定のシステムコール名を探している場合:

$ cat /proc/kallsyms | grep <sys_call_name>

すべてのシステムコールのリストを探している場合:

$ cat /proc/kallsyms
1
Hamed Kamrava