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。
参见
广告
|