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の定義と一致しません 。
質問
- どのファイルに
mkdirがあるか 実装? - 上記のような関数定義を使用して、どのファイルに実装が含まれているかを確認するにはどうすればよいですか?メソッドの定義と実装においてカーネルが従うパターンはありますか?
注:カーネル2.6.36-rc1を使用しています。
承認された回答:
システムコールは、通常の関数呼び出しのようには処理されません。ユーザースペースからカーネルスペースに移行するには、特別なコードが必要です。基本的には、呼び出しサイトでプログラムに挿入されるインラインアセンブリコードのビットです。システムコールを「キャッチ」するカーネル側のコードも、少なくとも最初は深く理解する必要のない低レベルのものです。
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です。つまり、システムコールは、独自のプログラム内の通常の関数呼び出しや、プログラムにリンクされたライブラリ内の関数へのアドレスではなく、番号で呼び出されます。上記のインラインアセンブリグルーコードは、これを使用してユーザーからカーネルスペースに移行し、パラメーターを一緒に取得します。
ここで少し奇妙なことを示すもう1つの証拠は、システムコールの厳密なパラメータリストが常にあるとは限らないことです:open(2) たとえば、2つまたは3つのパラメータを取ることができます。つまり、open(2) はオーバーロードされており、CではなくC ++の機能ですが、syscallインターフェイスはC互換です。 (これは、単一の関数が可変数の引数を取ることを可能にするCのvarargs機能と同じものではありません。)
最初の質問に答えるために、mkdir()が含まれる単一のファイルはありません。 存在します。 Linuxは多くの異なるファイルシステムをサポートしており、それぞれに「mkdir」操作の独自の実装があります。カーネルが単一のシステムコールの背後にあるものをすべて隠すことができる抽象化レイヤーは、VFSと呼ばれます。したがって、おそらくfs/namei.cを掘り下げ始めたいと思うでしょう。 、vfs_mkdir()を使用 。低レベルのファイルシステム変更コードの実際の実装は他の場所にあります。たとえば、ext4の実装はext4_mkdir()と呼ばれます 、fs/ext4/namei.cで定義 。
2番目の質問については、はい、これらすべてにパターンがありますが、単一のルールではありません。実際に必要なのは、特定のシステムコールを探す場所を見つけるために、カーネルがどのように機能するかをかなり広く理解することです。すべてのシステムコールにVFSが含まれるわけではないため、カーネル側のコールチェーンがすべてfs/namei.cで始まるわけではありません。 。 mmap(2) たとえば、mm/mmap.cで始まります 、カーネルのメモリ管理( "mm")サブシステムの一部だからです。
BovetとCesatiによる「UnderstandingtheLinuxKernel」のコピーを入手することをお勧めします。