目录
前言
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
可以发现,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"命令。
execlp()
该函数的定义为:
int execlp(const char *file, const char *arg, ...)该函数带 p,第一个参数是一个 *file,说明不需要带完好途径,它会在默认环境变量里面自动查找:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("hello!\n");
// 交换 main 进程
execl("ls","ls", "-a", NULL);
// good bye! 并不会被打印出来
printf("good bye!\n");
return 0;
}运行结果:
hello!
good bye!
说明,并没有胜利交换,这是我们带个 p:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("hello!\n");
// 交换 main 进程
execlp("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
胜利交换!其它的函数也是同理,就不再赘述了。
到此这篇关于exec()函数在C++中的应用及其用法的文章就介绍到这了,更多相关C++ exec()函数内容请搜索网站以前的文章或继续阅读下面的相关文章希望大家以后多多支持网站! |