【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


目录
打赏
0
0
0
0
16
分享
相关文章
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
133 1
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
78 34
|
14天前
|
Linux:守护进程(进程组、会话和守护进程)
守护进程在 Linux 系统中扮演着重要角色,通过后台执行关键任务和服务,确保系统的稳定运行。理解进程组和会话的概念,是正确创建和管理守护进程的基础。使用现代的 `systemd` 或传统的 `init.d` 方法,可以有效地管理守护进程,提升系统的可靠性和可维护性。希望本文能帮助读者深入理解并掌握 Linux 守护进程的相关知识。
28 7
|
13天前
|
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
32 5
Linux 进程管理基础
Linux 进程是操作系统中运行程序的实例,彼此隔离以确保安全性和稳定性。常用命令查看和管理进程:`ps` 显示当前终端会话相关进程;`ps aux` 和 `ps -ef` 显示所有进程信息;`ps -u username` 查看特定用户进程;`ps -e | grep &lt;进程名&gt;` 查找特定进程;`ps -p &lt;PID&gt;` 查看指定 PID 的进程详情。终止进程可用 `kill &lt;PID&gt;` 或 `pkill &lt;进程名&gt;`,强制终止加 `-9` 选项。
21 3
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
68 16
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
187 20
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
594 58
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
138 13