Linux进程替换

目录

一、进程替换

1.进程替换的概念

2.进程替换的原因

3.进程替换的本质

4.进程替换的方法

(1)函数的概述

(2)execl

(3)execv

(4)execlp

(5)execvp

(6)execle

(7)execve

(8)execvpe


一、进程替换

1.进程替换的概念

进程替换就是指将当前程序替换成一个新的程序,让当前进程执行这个新程序,如果替换成功了,原来的程序就不会被执行,也不会返回原来的返回值。

2.进程替换的原因

进程替换通常是在子进程中完成的,在学习进程替换之前,我们都是通过条件判断fork()的返回值使用子进程来执行父进程的一部分的代码,其实意义并不大。学习了进程替换可以使子进程执行一个全新的程序。

3.进程替换的本质

一个进程包含PCB,mm_struct(虚拟内存)等结构体,用来联系虚拟内存与物理内存的页表,以及程序的代码和数据。当进程中发生进程替换时,只有代码和数据发生替换,其他的内容不变。也就是说进程替换没有创建新的进程。

4.进程替换的方法

(1)函数的概述

进程运行起来时,它的代码和数据是要被加载到内存中的,是通过exec系列的函数来完成加载的。exec系列函数一共有七个,我们可以通过man手册来进行查询:

通过观察这几个函数我们发现它们都是在exec后面加入了几种后缀名。
可以通过后缀名的含义来进行区分记忆。

l:表示参数采用列表(以列表的方式一个一个传入进去)。
v:参数用数组。
p:有p自动搜索环境变量PATH(只要说名字就可以了,不用指明路径)。
e(env):表示自己维护的环境变量。(不用默认的环境变量)。

(2)execl

以l为后缀,说明以列表的形式传入参数。

int execl(const char *path, const char *arg, ...);

其中*path表示的是路径,arg表示的是要执行的陈鼓型,“...”表示的就是可变参数列表,及命令行上怎么执行就写入什么函数。必须以NULL作为参数列表的结束

#include<unistd.h>    
#include<stdio.h>    
#include<sys/wait.h>    
#include<stdlib.h>    
int main()    
{    
  if(fork()==0)    
  {    
    printf("command begin\n");    
    execl("/usr/bin/ls","ls","-a","-l",NULL);                                                                                                            
    printf("command fail\n");    
    exit(1);    
  }    
  waitpid(-1,NULL,0);    
  printf("wait child success\n");    
  return 0;    
}    

当执行子进程打印完“command begin”的语句的时候,进行进程替换。其中替换的是usr/bin/ls,在命令行要输入的是ls -a -l,将程序运行起来:

我们发现子进程被替换为了ls进程,并添加了-a  -l等选项。

(3)execv

execv的后缀是v,指的是以数组的形式输出参数。
只需要将上面的execl替换为如下即可。

      char* argv[]={"ls","-l","-a",NULL};    
      execv("/usr/bin/ls",argv);

其本质就是将参数列表放在了一个数组argv中。

(4)execlp
    execlp("ls","ls","-l","-a",NULL);    

就是将本来要指定的路径改成了通过环境变量进行查找。

(5)execvp

后缀为v和p,v表示以数组的形式,p表示的是不指名具体的路径去查找文件:

      char* argv[]={"ls","-l","-a",NULL};    
      execvp("ls",argv);   
(6)execle

后缀为l和e,e表示自己维护环境变量,不使用默认的环境变量。即向要执行的程序中导入环境变量:
建立两个程序一个程序完成进程替换,另一个程序为被替换的程序,负责打印自己的环境变量:

//mytest.c用来打印自身的环境变量
#include<stdio.h>    
#include<stdlib.h>    
#include<unistd.h>    
int main()    
{    
  extern char** environ;    
  int i;                                                                                                                                                 
  for(i=0;environ[i];i++)    
  {    
    printf("%d:%s\n",i,environ[i]);    
  }    
}   
//在myload.c中进行进程替换
      char* env[]={"MYENV1=hahaha","MYENV2=hehehe",NULL};    
      execle("./mytest","mytest",NULL,env);   

这里要注意的是已经指明了路径,在可变参数列表中可以不写入./
当我们不使用进程替换的时候,直接运行mytest,生成的是系统默认的环境变量:

如果通过进程替换执行mytest的话,它的环境变量就被定义成了env[],运行的结果是:

(7)execve

execve的代码同理:

      char* argv[]={"mytest",NULL};                                                                                                                      
      char* env[]={"MYENV1=hahaha","MYENV2=hehehe",NULL};    
      execve("./mytest",argv,env);   
(8)execvpe
      char* argv[]={"mytest",NULL};                                                                                                                      
      char* env[]={"MYENV1=hahaha","MYENV2=hehehe",NULL};    
      execve("./mytest",argv,env);   

由于p是在环境变量中找文件,那么就需要将我们新创建的文件添加到环境变量中,添加的方法为:

export PATH=$PATH:/home/用户名

此时执行的命令是:

其实所有的接口本质上无差别就是传递的参数不同而已,是为了满足不同的应用场景进行的封装。
操作系统实际上只提供了一个接口那就是:execve,其他的函数都是对该接口封装而成的库函数。它们的底层都是使用execve来进行实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值