Linux-Kernel

如何找到 Linux 核心系統呼叫的實現?

  • January 10, 2019

我試圖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

系統呼叫不像正常函式呼叫那樣處理。從使用者空間到核心空間的轉換需要特殊的程式碼,基本上是在呼叫站點將一些內聯彙編程式碼注入到您的程序中。“擷取”系統呼叫的核心端程式碼也是低級的東西,你可能不需要深入理解,至少一開始是這樣。

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 的varargs 特性不同,後者允許單個函式採用可變數量的參數。)

要回答您的第一個問題,不存在單個文件mkdir()。Linux 支持許多不同的文件系統,每個文件系統都有自己的“mkdir”操作實現。讓核心將所有內容隱藏在單個系統呼叫後面的抽象層稱為VFS。因此,您可能想開始探勘fs/namei.c, 與vfs_mkdir(). 低級文件系統修改程式碼的實際實現在別處。例如,呼叫 ext4 實現ext4_mkdir(),定義在fs/ext4/namei.c.

至於你的第二個問題,是的,這一切都有模式,但沒有一個規則。您真正需要的是對核心如何工作有相當廣泛的了解,以便確定您應該在哪裡查找任何特定的系統呼叫。並非所有系統呼叫都涉及 VFS,因此它們的核心端呼叫鏈並非都以fs/namei.c. mmap(2)例如,從 開始mm/mmap.c,因為它是核心記憶體管理(“mm”)子系統的一部分。

我建議您獲取一份由 Bovet 和 Cesati 撰寫的“ Understanding the Linux Kernel ”。

引用自:https://unix.stackexchange.com/questions/797