execve() - Unix、Linux系統呼叫
廣告
名稱
execve - 執行程式
概要
#include <unistd.h>
int execve(const char *filename, char *const argv[],
char *const envp[]);
|
描述
execve() 執行指向filename 的程式。filename必須是二進位制可執行檔案,或者是一個以“#! interpreter [arg]”形式的行開頭的指令碼。在後一種情況下,直譯器必須是可執行檔案的有效路徑名,它本身不是指令碼,將被呼叫為interpreter [arg] filename。
argv是傳遞給新程式的引數字串陣列。envp是字串陣列,通常為key=value形式,作為環境傳遞給新程式。argv和envp都必須以空指標結尾。被呼叫程式的main函式可以訪問引數向量和環境,當它定義為int main(int argc, char *argv[], char *envp[])時。
execve() 成功時不返回,呼叫程序的文字、資料、bss和堆疊將被載入的程式覆蓋。被呼叫的程式繼承呼叫程序的PID,以及任何未設定為close-on-exec的開啟檔案描述符。呼叫程序上掛起的訊號將被清除。任何設定為被呼叫程序捕獲的訊號都將重置為其預設行為。SIGCHLD訊號(當設定為SIG_IGN時)可能重置為SIG_DFL,也可能不重置。
如果當前程式正在被ptrace跟蹤,則成功執行execve()後,將向其傳送SIGTRAP。
如果filename指向的程式檔案中設定了set-user-ID位,並且呼叫程序沒有被ptrace跟蹤,則呼叫程序的有效使用者ID將更改為程式檔案所有者的有效使用者ID。類似地,當程式檔案的set-group-ID位被設定時,呼叫程序的有效組ID將設定為程式檔案的組。
程序的有效使用者ID被複制到已儲存的set-user-ID;類似地,有效組ID被複制到已儲存的set-group-ID。此複製發生在由於set-user-ID和set-group-ID許可權位而發生的任何有效ID更改之後。
如果可執行檔案是包含共享庫存根的a.out動態連結二進位制可執行檔案,則在執行開始時呼叫Linux動態連結器ld.so(8)將所需的共享庫載入到記憶體中,並將其與可執行檔案連結。
如果可執行檔案是動態連結的ELF可執行檔案,則PT_INTERP段中命名的直譯器用於載入所需的共享庫。對於與Linux libc版本5連結的二進位制檔案,此直譯器通常為/lib/ld-linux.so.1,對於與GNU libc版本2連結的二進位制檔案,此直譯器通常為/lib/ld-linux.so.2。
返回值
成功時,execve()不返回,錯誤時返回-1,並適當地設定errno。
錯誤
錯誤程式碼 | 描述 |
E2BIG | 環境 (envp) 和引數列表 (argv) 中的總位元組數太大。 |
EACCES | filename路徑字首的元件或指令碼直譯器名稱的搜尋許可權被拒絕。(另見path_resolution(2)。) |
EACCES | 檔案或指令碼直譯器不是普通檔案。 |
EACCES | 對檔案或指令碼或ELF直譯器的執行許可權被拒絕。 |
EACCES | 檔案系統已掛載為noexec。 |
EFAULT |
filename指向您可訪問的地址空間之外。 |
EINVAL | ELF可執行檔案有多個PT_INTERP段(即嘗試命名多個直譯器)。 |
EIO | 發生I/O錯誤。 |
EISDIR | ELF直譯器是一個目錄。 |
ELIBBAD | ELF直譯器格式不被識別。 |
ELOOP | 在解析filename或指令碼或ELF直譯器的名稱時遇到太多符號連結。 |
EMFILE | 程序已開啟最大數量的檔案。 |
ENAMETOOLONG |
filename太長。 |
ENFILE | 已達到系統對開啟檔案總數的限制。 |
ENOENT | 檔案filename或指令碼或ELF直譯器不存在,或者找不到檔案或直譯器所需的共享庫。 |
ENOEXEC | 可執行檔案格式不被識別,適用於錯誤的體系結構,或者具有其他格式錯誤,這意味著它無法執行。 |
ENOMEM | 核心記憶體不足。 |
ENOTDIR | filename路徑字首的元件或指令碼或ELF直譯器不是目錄。 |
EPERM | 檔案系統已掛載為nosuid,使用者不是超級使用者,並且檔案已設定SUID或SGID位。 |
EPERM | 程序正在被跟蹤,使用者不是超級使用者,並且檔案已設定SUID或SGID位。 |
ETXTBSY | 可執行檔案被一個或多個程序開啟以進行寫入。 |
符合標準
SVr4、4.3BSD、POSIX.1-2001。POSIX.1-2001未記錄#!行為,但在其他方面相容。
註釋
SUID和SGID程序不能被ptrace()跟蹤。Linux忽略指令碼上的SUID和SGID位。 掛載檔案系統nosuid的結果在Linux核心版本之間有所不同:有些會在這樣做會賦予使用者她之前沒有的許可權時拒絕執行SUID/SGID可執行檔案(並返回EPERM),有些只會忽略SUID/SGID位併成功exec()。
#!可執行shell指令碼的第一行允許的最大行長為127個字元。
歷史
在Unix V6中,exec()呼叫的引數列表以0結尾,而main的引數列表以-1結尾。因此,此引數列表不能直接用於進一步的exec()呼叫。從Unix V7開始,兩者都是NULL。
參見
廣告
|