【linux】进程替换

1.代码看现象

 #include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/wait.h>
 int main()
  {
      printf("test begin\n");
     int id=fork();//产生子进程
     if(id==0)
     {sleep(2);
     execl("/usr/bin/ls","ls","-l","-a",NULL);//子进程替换ls进程
     exit(1);//如果走到这里说明替换失败//替换失败的原因可能是因为无该进程
    }
     int status=0;
     int reid=waitpid(id,&status,0);//阻塞等待子进程的状态,等待回收资源
     if(reid>0)//说明子进程资源已经回收,子进程的进程号>0
     {
      printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));//子进程的退出码
     }
     printf("test end\n");
     return 0;            
  } 

在这里插入图片描述
在这里插入图片描述
1.疑问
为什么这里的退出码是0,不是1呢?
原因是由于子进程被替换成ls进程后,旧的子进程后面就不执行了,所以exit(1)这句代码就不会执行,而是执行新进程ls,而进程ls执行成功,所以退出码为0.
验证:
我们可以通过改变要替换的子进程不存在,就不会替换子进程,所以退出码会是1
在这里插入图片描述
2.execl函数参数分析
在这里插入图片描述


总结:1.execl函数,可以执行起来新的程序
2.execl函数,执行完毕后,后续的代码不见了,因为被替换了
3.execl函数的返回值可以不用关心,只要替换成功了,就不会往后继续进行了,只要继续运行了,一定是替换失败了

2.解释原理

在这里插入图片描述

3.进程替换(c替换c++)

子进程要替换的cpp程序

 include<iostream>
   #include<unistd.h>
   #include <sys/types.h>
   
   using namespace std;
   int main()
   {
   cout<<"this is c++"<<getpid()<<endl;
   cout<<"this is c+"<<getpid()<<endl;
   cout<<"this is c++"<<getpid()<<endl;
   cout<<"this is c++"<<getpid()<<endl;
   
  
  
                                                                                                                }

由于要编译两个程序,所以写个makefile来进行编译

.PHONY:all
   all:exe exe1 
exe:test.c
    gcc -o exe test.c
exe1:ans.cc
    g++ -o exe1 ans.cc -std=c++11
 .PHONY:clean
    rm -rf exe exe1 

在makefile里面他只会默认给第一个依赖列表通过依赖方法形成目标文makefile/make会自动根据文件中的依赖关系,进行自动推导,帮助我们执行所有相关的依赖方法.
test.c修改
在这里插入图片描述

在这里插入图片描述

4.其他的进程替换函数

1.int execv(const char *path, char *const argv[])

我们通过命令行参数表的形式获取执行该程序要怎么做

   #include<stdio.h>
   #include<unistd.h>
   #include<stdlib.h>
   #include<sys/types.h>
   #include<sys/wait.h>
   int main()
   {
   printf("test begin\n");
      int id=fork();
     if(id==0)
     { 
       sleep(2);
       char *const argv[]=
       {
     (char*)  "ls",
     (char*)  "-l",
      (char*) "-a",
      (char*) "--color",
       NULL
       };
      execv("/usr/bin/ls",argv);                                                                                     
     exit(1);
     }
     int status=0;
     int reid=waitpid(id,&status,0);
     if(reid>0)
         {
      printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));
    }
    printf("test end\n");
    return 0;
  }


命令行参数指针数组中要存对应指令以及选项的字符串地址,强转为char*,字符串的首地址
在这里插入图片描述

2.int execvp(const char *file, char *const argv[])

第一个参数直接写程序名称,p:代表路径会自动在环境变量PATH里面找
倒数第二个v:vector,用数组来记录程序怎么执行

 #include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/wait.h>
  int main()
  {
   printf("test begin\n");
      int id=fork();
     if(id==0)
     { 
       sleep(2);
       char *const argv[]=
       {
     (char*)  "ls",
     (char*)  "-l",
      (char*) "-a",
      (char*) "--color",
       NULL
      };
      execvp("ls",argv);                                                                                             
      exit(1);
     }
     int status=0;
     int reid=waitpid(id,&status,0);
    if(reid>0)
    {
      printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));
     }
     printf("test end\n");
     return 0;
  }

 

在这里插入图片描述

3.int execlp(const char *file, const char *arg, ...)

p:路径可以在PATH环境变量里面找

 #include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/types.h>
 #include<sys/wait.h>
 int main()
  {
   printf("test begin\n");
      int id=fork();
     if(id==0)
     { 
       sleep(2);
           execlp("ls","ls","-a","-l",NULL);                                                                     
      exit(1);
     }
     int status=0;
     int reid=waitpid(id,&status,0);                                                           
     if(reid>0)                                                                                
     {
     printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));
    }
     printf("test end\n");
    return 0;
  }


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7ddfc3e10ce248418d45e147fd7c86d5.png

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

`最后的e:表示环境变量
替换子进程的cpp

   #include<iostream>
   #include<unistd.h>
   #include <sys/types.h>
  
  using namespace std;
   int main(int argc,char*argv[],char*envp[])
   {
    for(int i=0;i<argc;i++)
   {cout<<argv[i]<<endl;}
   for(int i=0;envp[i];i++)
   {
    cout<<envp[i]<<endl;                                                                                             
  
  
  
   }
  
  
  }

  #include<stdio.h>
  #include<unistd.h>
  #include<stdlib.h>
  #include<sys/types.h>
  #include<sys/wait.h>
  int main()
   {
   printf("test begin\n");
     int id=fork();
     if(id==0)
     {
       sleep(2);
      char *const argv[]=
      {
     (char*)  "./",
     (char*)  "exe1",

       NULL
      };   
      char *const engv[]=
 
      {
        (char*)  "HELLO=1111111111",
        (char*)  "ERZI=22222222222",
       (char*) "SOUZI=33333333333",
        (char*) "GUIZI=44444444444",                                                                                 
       NULL
      };
      execvpe("exe1",argv,engv);
      exit(1);
     }
     int status=0;
     int reid=waitpid(id,&status,0);
     if(reid>0)
     {
      printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));
     }
     printf("test end\n");
     return 0;
  }
 

在这里插入图片描述

在这里插入图片描述
该cpp程序父进程是c程序,爷爷进程是bash,要获取爷爷的环境变量用上面的方法修改
在这里插入图片描述
总结第四个函数:
1.用全新的环境变量给子进程
2.用爷爷进程的环境变量给孙子进程,environ
3.老的环境变量加一些,putenv
而对应putenv,我们可以查一下手册

man putenv

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嘎嘎旺

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

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

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

打赏作者

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

抵扣说明:

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

余额充值