exec

    • 可加载可执行文件(ELF)或具有X权限的脚本
    • exec并不创建新进程,调用exec前后该进程id并未改变。
    • 进程调用exec函数以执行另一个程序,当前进程的用户空间代码和数据完全被新程序替代,从新程序启动例程开始执行。

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

int execvpe(const char *file, char *const argv[], char *const envp[]);

  • 不带字母p(标识path)的exec函数,第一参数必须是程序相对路径或绝对路径,eg. /bin/ls 或./a.out,而不能是ls或a.out。故其参数名为path。
  • 对于带p的函数,包含/表路径名;无路径在环境变量PATH列表中搜索程序。故其参数为file(可执行程序名)。
  • 按照惯例,argv或arg的第一参数(arg0, argv[0])为程序名,最后一参数为NULL。argv或arg包含程序名,是所有的命令行参数,如同main参数(argv[0]为程序名)。
  • l的函数要求将新程序的每个命令行参数都当作一个参数传给它,参数个数可变。list
  • v的函数要求参数以array数组形式传递。
  • e代表环境变量,最后一个参数为NULL,代表程序新的环境变量。不带e,表示新进程的环境变量来自原进程的外部变量environ。

失败-1,成功不返回。

execl("ls", "ls", "-al", NULL); 错误

execl("/bin/ls", "ls", "-al", NULL); 正确

char *exec_argv[3] = {"ls", "-al", NULL};
execvp("ls", exec_argv); 正确

execv("ls", exec_argv); 错误

示例

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(void)
{
    int pid;
    char *cmd[] = {"ls", "-al", NULL};

    pid = fork();
    if(pid == 0){ 
        execvp(cmd[0], cmd);
        printf("Can't exex ls\n");
        exit(-1);
    }   

    if(pid < 0){ 
        printf("Can't fork\n");
        exit(-1);
    } else {
        pid = waitpid(pid, NULL, 0); 
        printf("%d exit\n", pid);
    }   
    
    return 0;
}

在执行exec后,进程ID没有改变。除此之外,执行新程序的进程还保持了原进程的下列特征:

  • 进程ID和父进程ID。
  • 实际用户ID和实际组ID。
  • 附加组ID。
  • 进程组ID。
  • 会话ID。
  • 控制终端。
  • 闹钟尚余留的时间。
  • 当前工作目录。
  • 根目录。
  • 文件模式创建屏蔽字。
  • 文件锁。
  • 进程信号屏蔽。
  • 未处理信号。
  • 资源限制。
  • tms_utime、tms_stime、tms_cutime以及tms_cstime值。

对打开文件的处理与每个描述符的执行时关闭(close-on-exec)标志值有关。进程中每个打开描述符都有一个执行时关闭标志。若此标志设置,则在执行exec时关闭该描述符,否则该描述符仍打开。除非特地用fcntl设置了该标志,否则系统默认操作是在执行exec后仍保持这种描述符打开。

POSIX.1明确要求在执行exec时关闭打开的目录流。这通常是opendir函数实现的,它调用fcntl函数为对应于打开目录流的描述符设置执行时关闭标志。

注意,在执行exec前后实际用户ID和实际组ID保持不变,而有效ID是否改变则取决于所执行程序文件的设置用户ID位和设置组ID位是否设置。如果新程序的设置用户ID位已设置,则有效用户ID变成程序文件所有者的ID,否则有效用户ID不变。对组ID的处理方式与此相同。