Linuxカーネルシステムコールの実装を見つける方法は?

Linuxカーネルシステムコールの実装を見つける方法は?

mkdirカーネルのソースコードを見ながら、関数がどのように機能するかを理解したいと思います。これはカーネルの内部を理解し、さまざまな機能を探索する試みです。mkdirに定義されていることがわかりますsys/stat.h。プロトタイプが見つかりました。

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

これで、この関数がどのCファイルに実装されているかを確認する必要があります。ソースディレクトリで試しました。

ack "int mkdir"

示す

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

しかし、それらのどれもの定義を満たしていませんsys/stat.h

質問

  1. どのファイルがmkdir実装されますか?
  2. 上記の関数定義を使用して、どのファイルに実装があるかどうかを見つけることができますか?カーネルはメソッドを定義して実装するときにどのようなパターンに従いますか?

注:私はカーネルを使用しています。2.6.36-rc1

答え1

システムコールは通常の関数呼び出しとは異なる方法で処理されます。ユーザー空間からカーネル空間への変換を実装するには、特別なコードが必要です。デフォルトでは、一部のインラインアセンブリコードは呼び出しサイトからプログラムに挿入されます。システムコールを「キャッチする」カーネル側のコードも、少なくとも最初は深く理解する必要がない低レベルのコードです。

存在するinclude/linux/syscalls.hカーネルソースディレクトリには次のものがあります。

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

これで次のようになり/usr/include/asm*/unistd.hます。

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

このコードはmkdir(2)システムコール#83について話しています。つまり、システムコールは、プログラムの汎用関数呼び出しや、プログラムに接続されたライブラリの関数など、アドレスではなく数字で呼び出されます。上記のインラインアセンブリグルーコードは、それを使用してパラメータを使用してユーザー空間からカーネル空間に変換します。

状況が少し奇妙であるというもう一つの証拠は、システムコールが常に厳密な引数リストを持っているわけではないということです。open(2)たとえば、システムコールは2つまたは3つの引数を取ることができます。これはopen(2)例を意味しますオーバーロードC機能ではなくC ++機能ですが、システムコールインターフェイスはCと互換性があります。 (これはCとは異なります。可変パラメータ機能、単一の関数がさまざまな数の引数を取ることができるようにします。 )

最初の質問に答えると、単一のファイルは存在しませんmkdir()。 Linuxはそれぞれ独自に「mkdir」操作を実装するさまざまなファイルシステムをサポートしています。カーネルが単一のシステム呼び出しの後にすべてを隠すことを可能にする抽象化レイヤーを呼び出します。仮想FS。したがって、より深く掘り下げたい場合があり、低レベルのfs/namei.cファイルvfs_mkdir()システム修正コードの実際の実装は別の場所にあります。たとえば、ext4実装は次ext4_mkdir()のように定義されます。fs/ext4/namei.c

2番目の質問についてはそうです。すべてのパターンにはパターンがありますが、単一のルールはありません。実際に必要なのは、特定のシステムコールを見つける場所を特定するためにカーネルがどのように機能するかについてのかなり広範な理解です。すべてのシステムコールにVFSが含まれるわけではないため、カーネル側の呼び出しチェーンはすべてで始まりませんfs/namei.cmmap(2)mm/mmap.cこれは、カーネルメモリ管理(「mm」)サブシステムの一部であるためです。

「というコピーを入手することをお勧めします。Linuxカーネルについて学ぶボヴェとチェサティ。

答え2

straceこれはあなたの質問に直接答えることができないかもしれませんが、基本的なシステムコール、さらには最も簡単なシェルコマンドを理解しようとすると、とてもクールだと思います。例えば

strace -o trace.txt mkdir mynewdir

このコマンドのシステムコールは、mkdir mynewdirユーザーが確認できるようにTrace.txtにダンプされます。

答え3

Linuxカーネルのソースコードを読むのに最適な場所は次のとおりです。Linux相互参照(LXR)1. フリーテキスト検索結果に加えて、検索では型一致(関数プロトタイプ、変数宣言など)も返すので、通常のgrepよりも便利で高速です。

LXRはプリプロセッサ定義を拡張しません。システムコール名は、プリプロセッサによってどこでも破損します。ただし、ほとんどの(すべて?)システムコールは、次のいずれかで定義されます。SYSCALL_DEFINExマクロシリーズ。mkdir2つのパラメータが必要なので、以下を検索してください。SYSCALL_DEFINE2(mkdir~につながるmkdirシステムコール宣言:

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

さて、システムコールsys_mkdiratという意味なmkdiratので、クリックするとの宣言だけが見えますが、include/linux/syscalls.h定義は真上にあります。

mkdirat電話することが主な仕事である。vfs_mkdir(VFSは汎用ファイルシステム層です)。これをクリックすると、2 つの検索結果が表示されます。つまり、宣言include/linux/fs.hと数行以上の定義です。主な作業は、vfs_mkdirファイルシステム固有の実装を呼び出すことですdir->i_op->mkdir。方法を探すこれ一旦実装されると、単一のファイルシステムの実装に移動する必要があり、厳格で迅速なルールはありません。カーネルツリーの外側のモジュールでもかまいません。

1 LXRは索引付けプログラムです。既知のバージョンとWebインターフェイスのセットがわずかに異なるLXRインターフェイスを提供するいくつかのウェブサイトがあります。彼らは来て行く傾向があるので、おなじみのものが利用できない場合は、ウェブ上の「linux相互参照」を検索して他のものを見つけてください。

答え4

注: .h ファイルに定義機能。それ発表する対応する.hファイルにあり、他の場所で定義(実装)されました。これにより、コンパイラは関数シグネチャ(プロトタイプ)に関する情報を含むパラメータの型を調べ、戻り型をコードの呼び出しコンテキストと一致させることができます。

通常、Cの.h(ヘッダー)ファイルは関数を宣言し、マクロを定義するために使用されます。

mkdir特にシステムコール。 GNUがあるかもしれません。図書館これはシステムコールを囲むラッパーです(実際には確かです)。実際のカーネル実装は、mkdir特にカーネルソースコードとシステムコールを検索することで見つけることができます。

各ファイルシステムは、ある種のディレクトリ生成コードも実装します。 Virtual File System(VFS)層は、システム呼び出し層から呼び出すことができる共通APIを提供します。各ファイルシステムは、VFS層が呼び出す関数を登録する必要があります。これにより、さまざまなファイルシステムが独自のディレクトリ構造セマンティクスを実装できます(たとえば、特定のアイテムをより効率的に検索するためにいくつかのハッシュスキームを使用して保存する場合など)。 Linuxカーネルソースツリーを検索する場合は、これらのファイルシステム固有のディレクトリ生成機能を見つけることができるので、これに言及します。

関連情報