在fork后的子进程可以使用exec函数组,可以装入其他运行程序,子进程替换原有进程,做和父进程不一样的事。
1、使用exec函数的情况:
(1)、当进程认为自己再也不能为系统和用户做任何贡献时,就可以调用exec函数族让自己重生;
(2)、如果一个进程想要执行另外一个程序,那么他就可以调用一个fork函数新建一个进程,然后调用一个任意一个exec函数使子进程充重生。
exec函数:
(1) int execl(const char *path,const char *arg…..);(库函数)
(2) int execv(const char path,char const argv[]);(系统调用函数)
(3) int execle(const char path,const char *arg…..,char const envp[]);(库函数)
(4) int execve(const char* path,char* const argv[],char* const envp[]);(库函数)
(5) int execlp(const char file,const char arg,…);(库函数)
(6) int execvp(const char file,char const argv[]);(库函数)
v:vector//参数以数组形式
l:list//参数排列在后面
p:path//PATH环境变量,表示使用文件名,并从PATH环境下进行搜索。
e:envir//自己创建环境变量
2、exec函数的具体实现
(1)、当进程调用一个 exec函数时,该进程执行的程序完全替换为新程序,而新程序则从main函数开始执行。因为调用exec函数并不是创建新进程,所以前后进程的ID不变。
(2)、无路哪一个exec函数,都是讲可执行程序的路径,命令行参数和环境变量三个参数传递给可执行文件main()函数:
execv函数:通过路径名方式调用可执行文件作为新的进程映像,它的argv参数用来提供main()函数的argv参数,argv参数是一个可以加上一个以NULL结尾的字符串数组。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
char *argv[]={"ls","-l",NULL};
if(execv("/bin/ls",argv)==-1)
perror("execv"),exit(1);
}
execve函数 :参数path代表将要执行程序的路径名,参数argv与envp与main函数的参数相对应。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
char *argv[]={"ls","-l",NULL};
char *args[]={"th",NULL};
char *env[]={"1_shanghai","2_xian","3_nanjing"};
execve("./th",args,env);
}
execl函数:与execv函数用法类似,只是要显示的是指定的环境变量。环境变量位于命令行最后一个参数的后面,也就是位于空指针之后。
execl("/bin/ls","ls","-l",NULL);
execvp函数:与execv函数用法类似,不同的是参数名师file,该文件的参数,如果包含/,则视为路径名,否则就按PATH环境变量搜索就可以执行文件。
execvp(argv[0],argv);//第一个参数是可执行程序的名字,第二个参数是可执行文件
execlp函数:该函数与execl函数类似,他们的区别是参数名师file,该文件的参数,如果包含/,则视为路径名,否则就按PATH环境变量搜索就可以执行文件。
execlp("ls","ls","-l",NULL);
利用exec函数简单实例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
printf("before %d\n",getpid());
pid_t pid=fork();
if(pid==0){
char *arg[]={"ls","-l",NULL};
execvp("ls",arg);
}else{
while(1)
;
wait(NULL);
exit(0);
}
}