【linux】进程替换

简介: 【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;
  }

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
• 1


目录
相关文章
|
9月前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
11月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
330 32
|
7月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
270 67
|
6月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
160 16
|
6月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
127 20
|
5月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
115 0
|
5月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
144 0
|
5月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
107 0
|
5月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
104 0
|
9月前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
346 34