进程程序替换

一、进程替换原理

     使用fork函数创建子进程,子进程与父进程是共享代码与数据的,此时子进程运行的程序与父进程是相同的(但有可能是不同的分支),如果想让子进程运行自己的独立的程序就需要用到  exec函数执行新的程序。

        当一个进程被创建时,操作系统会为其创建进程控制块PCB地址空间并通过页表将虚拟地址映射到物理内存,而exec系列函数的进程替换原理就是将进程中的代码与数据替换为新的代码和数据,并将页表重新映射,此过程没有创建新的进程,所以exec系列函数调用前后进程pid并未发生改变

二、exec系列函数介绍

以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 execvpe(const char *file, char *const argv[],char *const envp[]);

#函数解释:

1.返回值:exec函数替换成功的返回值是没有意义的,因为若函数替换成功,就会加载新的程序,并执行,并不会返回,只有替换失败时会返回-1,所以exec函数只有失败的返回值没有成功的返回值

2.参数:

  • 函数第一个参数为path的是要传入待执行程序的存储路径
  • 为file的只需传入待执行程序的程序名即可
  • 形参列表中的三个点表示可变参数列表,可以传入不同个数的形参,但最后要以NULL结尾

3.命名理解:

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

#函数使用

int execl(const char *path, const char *arg, ...);
  #include<stdio.h>
  #include<unistd.h>
  #include<sys/types.h>
  #include<wait.h>
  #include<stdlib.h>
  int main()
 {
    pid_t id=fork();
    if(id==0)
    {
      //child
      //形参传列表
      execl("/usr/bin/ls","ls","-a","-l",NULL);                                                                                                                                                
    }
    else
    {
      int status=0;
     pid_t rid= waitpid(id,&status,0);
     if(rid>0)
     {
       printf("wait success child pid:%d child exit code\n",rid,WEXITSTATUS(status));
     }
    }
  }


int execv(const char *path, char *const argv[]);
  #include<stdio.h>
  #include<unistd.h>
  #include<sys/types.h>
  #include<wait.h>
  #include<stdlib.h>
  int main()
 {
    pid_t id=fork();
    if(id==0)
    {
      //child
       char* const argv[]={
       (char*) "ls",
       (char*) "-a",
       (char*) "-l",
        NULL
      };
       //形参传数组
       execv("/usr/bin/ls",argv);                                                                                                                                                   
    }
    else
    {
      int status=0;
     pid_t rid= waitpid(id,&status,0);
     if(rid>0)
     {
       printf("wait success child pid:%d child exit code\n",rid,WEXITSTATUS(status));
     }
    }
  }

int execvp(const char *file, char *const argv[]);
  #include<stdio.h>
  #include<unistd.h>
  #include<sys/types.h>
  #include<wait.h>
  #include<stdlib.h>
  int main()
 {
    pid_t id=fork();
    if(id==0)
    {
      //child
       char* const argv[]={
       (char*) "ls",
       (char*) "-a",
       (char*) "-l",
        NULL
      };
       //形参只需要传程序名字不需要路径
       execvp("ls",argv);                                                                                                                                                   
    }
    else
    {
      int status=0;
     pid_t rid= waitpid(id,&status,0);
     if(rid>0)
     {
       printf("wait success child pid:%d child exit code\n",rid,WEXITSTATUS(status));
     }
    }
  }

 int execvpe(const char *file, char *const argv[], char *const envp[]);

其实程序替换不仅可以替换系统命令还可以替换自己的程序,并且exec函数参数中的argv与env就是所谓的命令行参数表和环境变量表,在自己的程序中可以通过main函数传参访问定义的环境变量,当然也可以直接通过environ直接访问所有的环境变量,也可以通过putenv在原有环境变量中添加新的环境变量

exec.c:

  #include<stdio.h>
  #include<unistd.h>
  #include<sys/types.h>
  #include<wait.h>
  #include<stdlib.h>
  int main()
  {
    pid_t id=fork();
    if(id==0)
    {
        //child
       char* const argv[]=
       {
         (char*) "mypragma",
          NULL
       };
  
       char *const envp[]=
       {                                                                                                                                                                                       
          (char*)"HELLO=111111111111111",
          (char*)"HEHE=222222222222222222",
          NULL
       };
  
       execvpe("./mypragma",argv,envp);
    }
    else
    {
      int status=0;
      pid_t rid= waitpid(id,&status,0);
      if(rid>0)
      {
        printf("wait success child pid:%d child exit code\n",rid,WEXITSTATUS(status));
      }
    }
  }

mypragma.cc:

    #include<iostream>
    #include<stdio.h>                                                                                                                                                                          
    using namespace std;
    int main(int argc,char* argv[],char* env[])
    {
      int i=0;
      for( ;argv[i];i++)
      {
        printf("argv[%d]:%s\n",i,argv[i]);
      }
      printf("----------------------------------------\n");
      i=0;
      for( ;env[i];i++)
      {
        printf("env[%d]:%s\n",i,env[i]);
      }
      cout<<"hello world!\n"<<endl;
      cout<<"hello world!\n"<<endl;
      cout<<"hello world!\n"<<endl;
      cout<<"hello world!\n"<<endl;
    }

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张呱呱_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值