Linux_进程替换(execl...)

当我们fork()生成子进程后,子进程的代码与数据可以来自其他可执行程序。把磁盘上其他程序的数据以覆盖的形式给子进程。这样子进程就可以执行全新的程序了,这种现象称为程序替换。

文章目录

    • 1.进程替换注意事项
    • 2.替换函数(unistd.h)
    • execl
    • execlp
    • execv
    • execle
    • 替换函数的命名理解(execvp,execve)
    • 3.替换函数总结

1.进程替换注意事项

1.进程替换不会创建新进程,因为进程替换只是将该进程的数据替换为指定的可执行程序。而进程PCB没有改变,所以不是新的进程,进程替换后不会发生进程pid改变。

2.进程替换后,如果替换成功后则替换函数下的代码不会执行,因为进程替换是覆盖式的替换,替换成功后进程原来的代码就消失了。同理在进程替换失败后会执行替换函数后的代码

3.进程替换函数在进程替换成功后不返回,函数的返回值表示替换失败

4.进程替换成功后,退出码为替换后的进程的退出码

2.替换函数(unistd.h)

execl

函数原型
int execl(const char *path,const char *arg,…)

参数解释
path为可执行程序的路径,arg为如何执行这个可执行程序
…为可变参数,指的是给这执行程序携带的参数,在参数末尾加NULL表示参数结束

返回值:替换失败返回-1,替换成功不返回

eg:
Linux_进程替换(execl...)_第1张图片
Linux_进程替换(execl...)_第2张图片
观察上图发现进程替换成功后,替换函数下的打印没有执行,原因与注意事项的第二条相同

如果替换失败:
Linux_进程替换(execl...)_第3张图片
Linux_进程替换(execl...)_第4张图片

execlp

函数原型:
int execlp(const char *file, const char *arg,…)
参数解释:
file:要替换的目标程序,arg:如何执行这个程序,…为给这个程序传的参数。最后以NULL结束表示传参结束

返回值:进程替换失败后返回-1。

相比于execl :execp默认在Linux环境变量PATH中查找可执行程序

Linux环境变量

eg:
Linux_进程替换(execl...)_第5张图片

Linux_进程替换(execl...)_第6张图片

execv

函数原型:
int execv(const char* path,char* const argv[ ]);

参数解释:
argv数组:保存的是参数列表,将如何执行 可执行程序 和可执行程序需要的参数保存到字符串数组中,最后以NULL结尾表示参数结束,给execv
path:替换目标程序路径,

返回值:进程替换失败返回-1

eg:

Linux_进程替换(execl...)_第7张图片
Linux_进程替换(execl...)_第8张图片
可以发现argv数组与main函数的命令行参数相同
Linux_main函数命令行参数

execle

函数原型:
int execle(const char* path, const char* arg, …,char* const envp[ ])
参数解释:
path为替换的目标程序路径,arg与…表示如何执行替换后的程序以NULL结尾。
envp数组为要导入的环境变量
返回值:
替换失败返回-1
eg:
Linux_进程替换(execl...)_第9张图片
因为此时我们没有环境变量MYSTR所以第一行打印为空
Linux_进程替换(execl...)_第10张图片
这里在myProc子进程中用execle函数来导入环境变量MYSTR
Linux_进程替换(execl...)_第11张图片
Linux_进程替换(execl...)_第12张图片

注意:
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
#include
#include
#include
#include
#include

#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;
}

Linux_进程替换(execl...)_第13张图片

3.替换函数总结

函数名 参数传递形式 路径 是否导入环境变量
execl 列表 需要可执行程序路径 不导入 使用当前环境变量
execlp 列表 默认在环境变量中找 不导入 使用当前环境变量
execle 列表 需要可执行程序路径 导入 使用导入的环境变量
execv 数组 需要可执行程序路径 不导入 使用当前环境变量
execvp 数组 默认在环境变量中找 不导入 使用当前环境变量
execve 数组 需要可执行程序路径 导入 使用导入的环境变量

你可能感兴趣的