赞
踩
在进程间的程序替换
用fork创建子进程后执行的是和父进程相同的程序(但有可能执⾏行不同的代码分⽀支),
子进程往往要调用一种exec函数以执⾏行另⼀一个程序。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
调用exec并后该进程的id并未改变。不创建新进程,所以调用exec前后该进程的id并未改变。因此在task_struct中的其他信息并没有发生改变
其实有六种以exec开头的函数,统称exec函数:
#include <unistd.h>
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 execve(const char *path, char *const argv[], char *const envp[]);
1、使用execl:
带有字母l(表⽰示list)的exec函数要求将新程序的每个命令行参数都当作一个参数传给 它,命令行 参数的个数是可变的,因此函数原型中有…,…中的最后⼀一个可变参数应该是 NULL, 起sentinel的作用
#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t id=fork();
if(id==0)
{
printf("child start!\n");
sleep(3);
execl("/bin/ls","ls","-a","-l","-n","-i",NULL);
printf("child end!\n");
}
else
{
pid_t ret=wait(NULL);
if(ret>0)
{
printf("wait child success!\n");
}
}
return 0;
}
运行结果:
[admin@localhost linux8]$ ./wait
child start!
total 24
1054015 drwxrwxr-x. 2 500 500 4096 May 10 01:18 .
1053939 drwxrwxr-x. 7 500 500 4096 May 9 20:39 ..
1054019 -rw-rw-r–. 1 500 500 65 May 9 20:41 makefile
1054018 -rwxrwxr-x. 1 500 500 5224 May 10 01:18 wait
1054021 -rw-rw-r–. 1 500 500 2099 May 10 01:18 wait.c
wait child success!
在子进程中进行了程序的替换也就是ls程序的代码和数据替换了子进程的代码和数据
2、使用int execlp(const char *file, const char *arg, …);
不用加具体路径
不带字母p(表⽰示path)的exec函数 第⼀一个参数必须是程序的相对路径或绝对路径,例如 “/bin/ls”或”./a.out”,⽽而不能 是”ls”或”a.out”。对于带字母p的函数: 如果参数中包含/,则 将其视为路径名。 否则视为不带路径的程序名,在PATH环境变量的⽬目录列表中搜索这 个程序
int main()
{
pid_t id=fork();
if(id==0)
{
printf("child start!\n");
sleep(3);
execlp("ls","ls","-a","-l","-n","-i",NULL);
printf("child end!\n");
}
else
{
pid_t ret=wait(NULL);
if(ret>0)
{
printf("wait child success!\n");
}
}
return 0;
}
3、int execv(const char *path, char *const argv[]);
带有字母v(表⽰示vector)的函数,则应该先构造⼀一个指向各参数的指针数 组,然后将该数 组的⾸首地址当作参数传给它,数组中的最后⼀一个指针也应该是NULL,就像main函数 的 argv参数或者环境变量表⼀样。
int main()
{
pid_t id=fork();
if(id==0)
{
printf("child start!\n");
sleep(3);
char*_argv[]={"ls","-a","-l","-n","-i",NULL};
execv("/bin/ls",_argv);
printf("child end!\n");
}
else
{
pid_t ret=wait(NULL);
if(ret>0)
{
printf("wait child success!\n");
}
}
return 0;
}
4、int execvp(const char *file, char *const argv[]);
带有字母v(表⽰示vector)的函数,则应该先构造⼀一个指向各参数的指针数 组,然后将该数 组的⾸首地址当作参数传给它,数组中的最后⼀一个指针也应该是NULL,就像main函数 的 argv参数或者环境变量表⼀一样。
不带字母p(表⽰示path)的exec函数 第⼀一个参数必须是程序的相对路径或绝对路径,例如 “/bin/ls”或”./a.out”,⽽而不能 是”ls”或”a.out”。对于带字母p的函数: 如果参数中包含/,则 将其视为路径名。 否则视为不带路径的程序名,在PATH环境变量的⽬目录列表中搜索这 个程序。
int main()
{
pid_t id=fork();
if(id==0)
{
printf("child start!\n");
sleep(3);
char*_argv[]={"ls","-a","-l","-n","-i",NULL};
execvp("ls",_argv);
printf("child end!\n");
}
else
{
pid_t ret=wait(NULL);
if(ret>0)
{
printf("wait child success!\n");
}
}
return 0;
}
5、int execle(const char *path, const char *arg, …, char *const envp[]);
对于以e(表⽰示environment)结尾的exec函数,可以把一份新的环境变量表传给它,其他 exec函数 仍使⽤用当前的环境变量表执行新程序
#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
pid_t id=fork();
if(id==0)
{
printf("child start\n");
char* envTable[]={"MYENV=/hello/word/aa/bb/cc/xx/yy",NULL};
execle("./myenv","myenv",NULL,envTable);
}
else
{
pid_t ret=wait(NULL);
printf("father end \n");
}
return 0;
}
#include<stdio.h>
int main()
{
printf("MYENV is %s\n",getenv("MYENV"));
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。