execve() 系统调用

execve() 系统调用的作用是运行另外一个指定的程序。它会把新程序加载到当前进程的内存空间内,当前的进程会被丢弃,它的堆、栈和所有的段数据都会被新进程相应的部分代替,然后会从新程序的初始化代码和 main 函数开始运行。同时,进程的 ID 将保持不变。

execve() 系统调用通常与 fork() 系统调用配合使用。从一个进程中启动另一个程序时,通常是先 fork() 一个子进程,然后在子进程中使用 execve() 变身为运行指定程序的进程。 例如,当用户在 Shell 下输入一条命令启动指定程序时,Shell 就是先 fork() 了自身进程,然后在子进程中使用 execve() 来运行指定的程序。

execve() 系统调用的函数原型为:

int execve(const char *filename, char *const argv[], char *const envp[]);
  •  

filename 用于指定要运行的程序的文件名,argv 和 envp 分别指定程序的运行参数和环境变量。除此之外,该系列函数还有很多变体,它们执行大体相同的功能,区别在于需要的参数不同,包括 execl、execlp、execle、execv、execvp、execvpe 等。它们的参数意义和使用方法请读者自行查看帮助手册。

需要注意的是,exec 系列函数的返回值只在遇到错误的时候才有意义。如果新程序成功地被执行,那么当前进程的所有数据就都被新进程替换掉了,所以永远也不会有任何返回值。

对于已打开文件的处理,在 exec() 系列函数执行之前,应该确保全部关闭。因为 exec() 调用之后,当前进程就完全变身成另外一个进程了,老进程的所有数据都不存在了。如果 exec() 调用失败,当前打开的文件状态应该被保留下来。让应用层处理这种情况会非常棘手,而且有些文件可能是在某个库函数内部打开的,应用对此并不知情,更谈不上正确地维护它们的状态了。

所以,对于执行 exec() 函数的应用,应该总是使用内核为文件提供的执行时关闭标志(FD_CLOEXEC)。设置了该标志之后,如果 exec() 执行成功,文件就会被自动关闭;如果 exec() 执行失败,那么文件会继续保持打开状态。使用系统调用 fcntl() 可以设置该标志。

### execve系统调用的使用方法与参数详解 `execve` 是 Linux 系统中用于执行新程序的一个重要系统调用。它的主要功能是用指定的可执行文件替换当前进程的映像,从而执行新的程序[^1]。以下是 `execve` 的详细使用方法和参数说明: #### 函数原型 ```c int execve(const char *filename, char *const argv[], char *const envp[]); ``` #### 参数详解 1. **`filename`** - 类型:`const char *` - 描述:指向要执行的可执行文件路径的字符串。可以是绝对路径或相对路径。如果提供的路径无效或不可访问,系统调用将返回错误[^3]。 2. **`argv`** - 类型:`char *const []` - 描述:指向一个以 NULL 结尾的字符串数组,这些字符串作为命令行参数传递给新程序。数组的第一个元素通常是程序名称,最后一个元素必须为 NULL,以标识参数列表的结束[^4]。 3. **`envp`** - 类型:`char *const []` - 描述:指向一个以 NULL 结尾的字符串数组,表示环境变量。每个字符串的形式为 `key=value`。如果不需要传递任何环境变量,可以将此参数设置为 NULL[^3]。 #### 返回值 - 如果 `execve` 成功执行,当前进程会被新程序替换,因此不会返回到调用者代码。 - 如果发生错误,`execve` 将返回 `-1`,并设置全局变量 `errno` 来指示具体的错误原因[^4]。 #### 示例代码 以下是一个简单的示例,展示如何使用 `execve` 执行外部程序: ```c #include <stdio.h> #include <unistd.h> int main() { // 定义要执行的程序路径 const char *filename = "/bin/ls"; // 定义命令行参数 char *argv[] = {"ls", "-l", "/tmp", NULL}; // 定义环境变量 char *envp[] = {"PATH=/usr/bin:/bin", "HOME=/root", NULL}; // 调用 execve if (execve(filename, argv, envp) == -1) { perror("execve failed"); return 1; } return 0; } ``` #### 注意事项 - **进程替换**:`execve` 不会创建新进程,而是用指定的程序替换当前进程的映像。这意味着原进程的代码、数据段、堆栈等都会被新程序覆盖[^4]。 - **继承特性**:新程序继承调用者的 PID 和打开的文件描述符(除非设置了 `close-on-exec` 标志)。此外,挂起的信号会被清除,捕获的信号会被重置为其默认行为。 - **错误处理**:由于 `execve` 成功时不会返回,因此只有在调用失败时才会返回 `-1`。因此,通常需要检查返回值,并结合 `perror` 或 `strerror` 输出错误信息[^3]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值