如何呼叫來自 man 2 的系統呼叫?
通過系統呼叫,我指
man 2 brk
的是函式,而不是0x80
中斷。如果我正確理解了這個執行緒,編譯的 C 程序永遠不會直接呼叫系統呼叫。它只能呼叫庫呼叫,這些呼叫可能是從
glibc
.但是,
man 3 brk
返回No manual entry for brk in section 3
. 因此,我想必鬚髮生以下情況之一brk
才能正確執行:
- 我上面的理解是錯誤的。
glibc
程序可以在沒有支持的情況下呼叫系統呼叫。但是如何brk
連結到程序中呢?- 系統呼叫確實有一個
glibc
包裝器brk
。那麼brk
當我包含哪個#include <unistd.h>
呢?一glibc
還是系統呼叫一?如果它是glibc
一個,為什麼它沒有記錄在man 3
?在哪裡可以找到可用庫呼叫的完整列表?
對於第 2 節中帶有手冊頁的大多數係統呼叫,手冊頁實際上描述了 C 庫包裝器。通常明確提到例外情況,就像
gettid
@Sergei Kurenkov 在他們的回答中提到的那樣:注意Glibc 沒有為這個系統呼叫提供包裝;使用 syscall(2) 呼叫它。
pivot_root
與(對於一般應用程序沒有那麼有用)類似,tgkill
(它執行 的低級功能pthread_kill
)。然後是readdir
,實際的系統呼叫與庫函式有些不同:描述這不是您感興趣的函式。查看 readdir(3) 以獲得符合 POSIX 的 C 庫介面。此頁面記錄了被 getdents(2) 取代的裸核心系統呼叫介面。
請注意,必須有某種包裝器。函式呼叫是使用 C 呼叫約定進行的,這與核心介面的呼叫約定不同。通常的函式呼叫是使用
call
彙編指令(或類似指令)進行的,核心呼叫使用syscall
orint 0x80
(這不包括像gettimeofday
orgetpid
中的東西vdso
)。編譯器不需要(不需要)知道哪個函式呼叫映射到一個實際的核心呼叫。即使使用“正常”系統呼叫,C 庫包裝器的行為也與裸系統呼叫略有不同:系統呼叫將錯誤程式碼作為不同的負值返回(如果您查看 Linux 核心程式碼,您會看到很多返回像
return -EPERM;
)。C 庫包裝器將所有此類返回值轉換為 -1,並將實際錯誤程式碼移動到errno
.