Linux_进程替换(execl、execlp、execv、execle)
当我们fork()生成子进程后,子进程的代码与数据可以来自其他可执行程序。把磁盘上其他程序的数据以覆盖的形式给子进程。这样子进程就可以执行全新的程序了,这种现象称为程序替换。文章目录1.替换函数(1.替换函数(<unistd.h>)...
当我们fork()生成子进程后,子进程的代码与数据可以来自其他可执行程序。把磁盘上其他程序的数据以覆盖的形式给子进程。这样子进程就可以执行全新的程序了,这种现象称为程序替换。
1.进程替换注意事项
1.进程替换不会创建新进程,因为进程替换只是将该进程的数据替换为指定的可执行程序。而进程PCB没有改变,所以不是新的进程,进程替换后不会发生进程pid改变。
2.进程替换后,如果替换成功后则替换函数下的代码不会执行,因为进程替换是覆盖式的替换,替换成功后进程原来的代码就消失了。同理在进程替换失败后会执行替换函数后的代码
3.进程替换函数在进程替换成功后不返回,函数的返回值表示替换失败
4.进程替换成功后,退出码为替换后的进程的退出码
2.替换函数(unistd.h)
execl
函数原型
int execl(const char *path,const char *arg,…)
参数解释
path为可执行程序的路径,arg为如何执行这个可执行程序
…为可变参数,指的是给这执行程序携带的参数,在参数末尾加NULL表示参数结束
返回值:替换失败返回-1,替换成功不返回
eg:
观察上图发现进程替换成功后,替换函数下的打印没有执行,原因与注意事项的第二条相同
如果替换失败:
execlp
函数原型:
int execlp(const char *file, const char *arg,…)
参数解释:
file:要替换的目标程序,arg:如何执行这个程序,…为给这个程序传的参数。最后以NULL结束表示传参结束
返回值:进程替换失败后返回-1。
相比于execl :execp默认在Linux环境变量PATH中查找可执行程序
eg:
execv
函数原型:
int execv(const char* path,char* const argv[ ]);
参数解释:
argv数组:保存的是参数列表,将如何执行 可执行程序 和可执行程序需要的参数保存到字符串数组中,最后以NULL结尾表示参数结束,给execv
path:替换目标程序路径,
返回值:进程替换失败返回-1
eg:
可以发现argv数组与main函数的命令行参数相同
Linux_main函数命令行参数
execle
函数原型:
int execle(const char* path, const char* arg, …,char* const envp[ ])
参数解释:
path为替换的目标程序路径,arg与…表示如何执行替换后的程序以NULL结尾。
envp数组为要导入的环境变量
返回值:
替换失败返回-1
eg:
因为此时我们没有环境变量MYSTR所以第一行打印为空
这里在myProc子进程中用execle函数来导入环境变量MYSTR
注意:
1.导环境变量的数组最后以NULL结尾
2.导入环境变量后原系统环境变量的值被清空,这种导入环境变量的方式为覆盖式导入
替换函数的命名理解(execvp,execve)
替换函数前面的exec不变
l:参数采用列表
v:参数采用数组
p:不需要输入路径,在环境变量自动搜索
e:要导入自己的环境变量
所以execvp表示不需要输入路径,参数用数组传
execve表示需要输入路径,参数用数组传,自己维护环境变量
execvp拓展_简易shell
我们在命令行输入的命令可以用函数fgets来获取
定义一个字符数组
char Shell[100]
fgets(Shell,100,stdin);这样就可以将我们的命令存起来。
因为不同参数之间用空格相隔,所以我们可以用字符串分割函数strtok来分割处理成字符串存到数组中。
strtok函数在没有找到或者最后一次找到时返回NULL,这个函数可以将字符串分割为多个字符串。
execvp:不需要路径,参数用数组传,而strtok分割的正好为命令的参数,我们输入的命令又在环境变量中
所以我们利用进程替换可以实现简易的shell
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#define MAXLEN 1024
#define LEN 32
int main()
{
char shell[MAXLEN]={0};
char* DOS[LEN]={0};//保存处理后的参数
while(1)
{
printf("[dodamce@My_centos dir] ");
fgets(shell,MAXLEN,stdin);
shell[strlen(shell)-1]='\0';
DOS[0]=strtok(shell," ");
int i=1;
while(DOS[i]=strtok(NULL," "))//strtok按照空格拆分字符串,并且将其存到DOS字符串数组中
{
i++;
}
pid_t id=fork();//创建子进程
if(id==0)
{
//child
execvp(DOS[0],DOS);//不需要路径,DOS第一个元素就是我们要替换的可执行程序
exit(1);
}
int status=0;//父进程阻塞等待,接受并打印子进程的退出码,防止僵尸进程
pid_t wait=waitpid(id,&status,0);
if(wait>0)
{
printf("Exit Code=%d\n",WEXITSTATUS(status));
}
}
return 0;
}
3.替换函数总结
函数名 | 参数传递形式 | 路径 | 是否导入环境变量 |
---|---|---|---|
execl | 列表 | 需要可执行程序路径 | 不导入 使用当前环境变量 |
execlp | 列表 | 默认在环境变量中找 | 不导入 使用当前环境变量 |
execle | 列表 | 需要可执行程序路径 | 导入 使用导入的环境变量 |
execv | 数组 | 需要可执行程序路径 | 不导入 使用当前环境变量 |
execvp | 数组 | 默认在环境变量中找 | 不导入 使用当前环境变量 |
execve | 数组 | 需要可执行程序路径 | 导入 使用导入的环境变量 |
更多推荐
所有评论(0)