exec()函数在C++中是一个进程操控函数,用于创立新进程履行其他程序或命令行指令。exec()函数能够替换当前进程的代码和数据,创立新的进程运行其他程序。exec()函数有多个版别,例如execl、execv、execle、execve等,根据不同的参数类型和个数来运用。

前语

fork 函数之后,假如想要把子进程换成一个我想要履行的进程,这时,就不得不运用 exec()函数了,这也是 fork()的含义地点。当然,exec系列的函数也能够将当前进程替换掉,不一定非要fork()一个子进程。常见的fork()调用比如有很多,比方从 wechat发起一个语音电话、从 bash或许zsh履行一个 a.out 程序,都是在利用exec体系调用将新产生的子进程彻底替换成方针进程。

比方,这是一个死循环程序(目的是为了调查,让它活得久一点):

#include <stdio.h>
int main() {
    int a = 0;
    while (1) {
        a++;
    }
    return 0;
}

经过编译,履行:

    gcc fork_example.c -o fork_example

    ./fork_example

检查进程:top

C++中的exec()函数

能够发现,fork_example的进程的 PPID 为 54861,咱们看看它是谁:ps 54861

  PID   TT  STAT      TIME COMMAND
54861 s018  Ss     0:00.23 /bin/zsh -il

很明显,它是 zsh,现在能够终止fork_example:kill 57892

zsh: terminated ./fork_example

程序就会结束!以上比如,能够看到咱们的子进程,便是由一个父进程fork()之后替换的。

exec()

#include<unistd.h>

原型:

int execl(const char *path, const char *arg, ...)
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg, ..., char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, ...)
int execvp(const char *file, char *const argv[])

参数:

path参数表明你要发动程序的名称,包括途径名;

arg参数表明发动程序所带的参数,一般第一个参数为要履行命令名

回来值:成功回来0,失利回来-1

上述exec系列函数底层都是经过execve体系调用实现:

#include <unistd.h>int execve(const char *filename, char *const argv[],char *const envp[]);#include <unistd.h>
int execve(const char *filename, char *const argv[],char *const envp[]);

① 查找方法:上表其间前4个函数的查找方法都是完好的文件目录途径,而最终2个函数(也便是以p结尾的两个函数)能够只给出文件名,体系就会主动从环境变量“$PATH”所指出的途径中进行查找。

② 参数传递方法:exec函数族的参数传递有两种方法,一种是逐个罗列的方法,而另一种则是将所有参数整体构造成指针数组进行传递。

在这里参数传递方法是以函数名的第5位字母来区分的,字母为“l”(list)的表明逐个罗列的方法,字母为“v”(vertor)的表明将所有参数整体构造成指针数组传递,然后将该数组的首地址当做参数传给它,数组中的最终一个指针要求是NULL。读者能够调查execl、execle、execlp的语法与execv、execve、execvp的差异。

③ 环境变量:exec函数族运用了体系默认的环境变量,也能够传入指定的环境变量。这里以“e”(environment)结尾的两个函数execle、execve就能够在envp[]中指定当前进程所运用的环境变量替换掉该进程承继的所以环境变量,这极大地供给了灵敏度。

execl()

该函数的定义为:

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

能够看到,它的参数为一个 path,因为不带 p,因此,最终一个参数为 NULL

例如:

#include <stdio.h>
#include <unistd.h>
int main() {
    printf("hello!\n");
    // 替换 main 进程
    execl("/bin/ls", "ls", "-a", NULL);
    // good bye! 并不会被打印出来
    printf("good bye!\n");
    return 0;
}

履行成果:

hello!
.               a.out           execlp.c        fork_example    myshell.c
..              execl.c         fork.c          fork_example.c

能够看到,它成功地履行了"ls -a"命令。