0


进程控制【Linux】

文章目录

创建一批子进程

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#defineN5voidrunChild(){int cnt =10;while(cnt !=0){printf("i am a child : %d , ppid:%d\n",getpid(),getppid());sleep(1);
        cnt--;}}intmain(){int i =0;for(; i < N; i++){
        pid_t id =fork();if(id ==0){//子进程runChild();exit(0);}//父进程//父进程继续循环}sleep(1000);return0;}

进程终止

进程退出只有三种情况:
代码运行完毕,结果正确。
代码运行完毕,结果不正确
代码异常终止(进程崩溃)

代码异常,本质可能就是代码没有跑完
此时进程的退出码无意义,我们不关心退出码

代码是否正确,统一会采用进程的退出码来进行判断

在这里插入图片描述

查看该进程的进程退出码
$?:保存的是最近一次进程退出的时候的退出码

[cxq@iZ7xviiy0goapxtblgih6oZ lesson15]$ echo $?

在这里插入图片描述

查看错误码
在这里插入图片描述

在这里插入图片描述

errno

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<errno.h>intmain(){int ret =0;char*p =(char*)malloc(1000*1000*1000*4);if(p ==NULL){//errno 返回的是错误码 ,strerror可以知道错误原因printf("malloc error, %d %s\n", errno,strerror(errno));
        ret = errno;}else{printf("malloc success\n");}return ret;}

在这里插入图片描述

进程出现异常,本质是我们的进程收到了对应的信号
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

exit与return的区别
exit在任意地方被调用,都表示调用进程直接退出
return只表示当前函数返回,还会继续向后运行

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<errno.h>voidshow(){printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");exit(13);//exit在任意地方被调用,都表示调用进程直接退出,如果此时换成return,return只表示当前函数返回,还会继续向后运行printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");}intmain(){show();printf("hello Linux\n");return12;}

在这里插入图片描述

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<errno.h>voidshow(){printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");return;//return只表示当前函数返回,还会继续向后运行exit(13);//exit在任意地方被调用,都表示调用进程直接退出printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");}intmain(){show();printf("hello Linux\n");return12;}

在这里插入图片描述
_exit :

#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<string.h>#include<errno.h>voidshow(){printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");printf("hello show\n");_exit(14);printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");printf("end show\n");}intmain(){show();printf("hello Linux\n");return12;}

在这里插入图片描述
_exit 与exit的区别

使用exit函数退出进程也是我们常用的方法,exit函数可以在代码中的任何地方退出进程,并且exit函数在退出进程前会做一系列工作

1、执行用户通过atexit或on_exit定义的清理函数。
2、关闭所有打开的流,所有的缓存数据均被写入。
3、调用_exit函数终止进程。
在这里插入图片描述

在这里插入图片描述

_exit()是系统调用接口,exit()是库函数
当把exit改成_exit时,使用_exit终止进程,不会刷新缓冲区的数据,所以缓冲区当中的数据将不会被输出,就不会看到you can see me 了
但是exit在终止进程之前,会冲刷缓冲区,将缓冲区的数据输出

printf一定是先把数据写入缓冲区中,合适的时候,再进行刷这个缓冲区,缓冲区绝对不在内核中,在用户区

进程等待

进程等待:通过系统调用wait/waitpid,来进行对子进程进行状态检测与回收的功能

1、子进程退出,父进程如果不读取子进程的退出信息,子进程就会变成僵尸进程,进而造成内存泄漏
2、进程一旦变成僵尸进程,那么就算是kill -9命令也无法将其杀死,因为谁也无法杀死一个已经死去的进程
3、对于一个进程来说,最关心自己的就是其父进程,因为父进程需要知道自己派给子进程的任务完成的如何
4、父进程需要通过进程等待的方式,回收子进程资源,获取子进程的退出信息

父进程通过调用wait/waitpid进行僵尸进程的回收问题

在这里插入图片描述
监控脚本

while :;dops ajx |head -1 && ps ajx | grep testWait | grep -v grep  ;sleep 1 ;echo"------------"; done

在这里插入图片描述

wait是等待任意一个子进程退出

如果是多个子进程僵尸,如何利用wait回收?

1#include<stdio.h>2#include<unistd.h>3#include<stdlib.h>4#include<sys/types.h>5#include<sys/wait.h> 6#define N 10 7   void     Runchild ()8{9   int cnt =5;10   while(cnt)11{12     printf("child pid:%d ,ppid%d\n",getpid() ,getppid());13     sleep(1);14     cnt--;15}16}17 int main()18{19   for( int i =0; i < N ;i ++ )20{21     pid_t id=  fork();22     if(id==0)23{24       //子进程
 25       Runchild ();26       exit(0);27}28     //父进程      
 29     printf("create child process: %d success\n", id);30}31   sleep(10);32   //等待                                             
 33   for( int i =0; i < N  ; i++ )34{35       pid_t id=  wait(NULL);36      if( id>0)37{38        printf("wait %d success\n", id);39}4041}4243 sleep(5);44return0;45}

在这里插入图片描述

如果父进程在等待子进程,如果一个子进程或多个子进程不退出 ,父进程会在调用wait时,父进程就一直拿不到子进程的pid , 父进程会一直等待子进程退出,父进程这种状态叫阻塞等待

#include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/wait.h> 
  6 #define N 10 
  7   void     Runchild ()
  8 {
  9   int cnt =5 ;
 10   while(1)
 11   {
 12     printf("child pid:%d ,ppid%d\n",getpid(),getppid());
 13     sleep(1);
 14     cnt--;
 15   }
 16 }
 17 int main()
 18 {
 19   for( int i =0 ; i < N ;i ++)
 20   {
 21     pid_t id  =  fork();
 22     if( id ==0  )
 23     {
 24       //子进程
 25       Runchild ();
 26       exit(0);
 27     }
 28     //父进程 
 29     printf("create child process: %d success\n", id);
 30   }
 31 //sleep(10);                                                                                                                                             
 32   //等待
 33   for( int i = 0 ; i < N  ; i++)
 34   {
 35       pid_t id   =  wait(NULL);
 36      if( id>0 )
 37      {
 38        printf("wait %d success\n", id);
 39      }
 40 
 41   }
 42 
 43 sleep(5);
 44   return 0 ;
 45 }

waitpid

等待指定子进程或任意子进程

在这里插入图片描述

waitpid的返回值:
1、等待成功返回被等待进程的pid。
2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0。
3、如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在。

pid:待等待子进程的pid,若设置为-1,则等待任意子进程
status:输出型参数(通过指针,把函数内部的数据带出来)
获取子进程的退出状态,不关心可设置为NULL

status:操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107voidRunchild()8{9int cnt =5;10while(1)11{12printf("child pid:%d ,ppid%d\n",getpid(),getppid());13sleep(1);14     cnt--;15}16}17intmain()18{45   pid_t id =fork();46if(id <0)47{48perror("fork");49return1;50}51elseif( id ==0)52{53//child 5455int cnt =5;56while(cnt)57{58printf("I am a child ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);59      cnt --;60sleep(1);61}62exit(1);63}64else// parent 65{66int cnt =10;67while(cnt )68{69printf("I am a parent ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);70      cnt --;71sleep(1);72}73// pid_t ret = wait(NULL);7475int status =0;//输出型参数76//操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中77    pid_t  ret =waitpid( id,&status ,0);7879//等待成功80if( ret ==id )//id是子进程的pid81{82//status存放的是子进程的退出信息83printf("wait success,ret:%d, status: %d\n", ret, status);84}85sleep(5);868788}89return0;90}

在这里插入图片描述
为什么status是256 ?
在子进程中 ,exit函数里面,我们设置的是1
在这里插入图片描述

退出码设置的是1 ,也就是00000001,00000001就是256

子进程退出,一共会有3种退出场景
1、代码运行完毕,结果正确
2、代码运行完毕,结果不正确
3、代码异常终止

父进程等待,需要获得子进程退出的哪些信息?
1、子进程代码是否异常
2、如果没有异常,通过退出码判断来结果是否正确
不同的退出码表示不同的出错原因

status是一个整型变量,但status不能简单的当作整型来看待,status的不同比特位所代表的信息不同,具体细节如下(只研究status低16比特位)

在这里插入图片描述

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107voidRunchild()8{9int cnt =5;10while(1)11{12printf("child pid:%d ,ppid%d\n",getpid(),getppid());13sleep(1);14     cnt--;15}16}17intmain()18{45   pid_t id =fork();46if(id <0)47{48perror("fork");49return1;50}51elseif( id ==0)52{53//child 5455int cnt =5;56while(cnt)57{58printf("I am a child ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);59      cnt --;60sleep(1);61}62exit(1);63}64else// parent 65{66int cnt =10;67while(cnt )68{69printf("I am a parent ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);70      cnt --;71sleep(1);72}73// pid_t ret = wait(NULL);7475int status =0;//输出型参数76//操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中77    pid_t  ret =waitpid( id,&status ,0);7879//等待成功80if( ret ==id )//id是子进程的pid81{82//status存放的是子进程的退出信息83//7F 0111 1111 84//0xFF85printf("wait success,ret:%d, exit sig : %d, exit code:%d\n", ret, status&0x7F,(status>>8)&0xFF);//打印的分别是 id, 信号, 退出码86}87sleep(5);888990}91return0;92}

在这里插入图片描述

通过收到信号判断是否异常
通过看退出码判断是否结果正确

系统当中提供了两个宏来获取退出码和退出信号
WIFEXITED(status):用于查看进程是否是正常退出,本质是检查是否收到信号
WEXITSTATUS(status):用于获取进程的退出码

exitNormal =WIFEXITED(status);//获取退出信号,判断是否正常退出
exitCode =WEXITSTATUS(status);//获取退出码

例如:

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107voidRunchild()8{9int cnt =5;10while(1)11{12printf("child pid:%d ,ppid%d\n",getpid(),getppid());13sleep(1);14     cnt--;15}16}17intmain()18{45   pid_t id =fork();46if(id <0)47{48perror("fork");49return1;50}51elseif( id ==0)52{53//child 5455int cnt =5;56while(cnt)57{58printf("I am a child ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);59      cnt --;60sleep(1);61}62exit(1);63}64else// parent 65{66int cnt =10;67while(cnt )68{69printf("I am a parent ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);70      cnt --;71sleep(1);72}73// pid_t ret = wait(NULL);7475int status =0;//输出型参数76//操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中77    pid_t  ret =waitpid( id,&status ,0);7879//等待成功80if( ret ==id )//id是子进程的pid81{82//status存放的是子进程的退出信息83//7F 0111 1111 84//0xFF85//printf("wait success,ret:%d, exit sig : %d, exit code:%d\n",      ret, status&0x7F , (status>>8) &0xFF  ); //打印的分别是 id, 信号, 退出码if(WIFEXITED(status))88{89printf("进程是正常跑完的,退出码:%d\n",WIFEXITED(status));90}91else92{93printf("进程出异常了\n");94}86}87sleep(5);888990}91return0;92}

以下代码中同时创建了10个子进程
父进程再使用waitpid函数指定等待这10个子进程

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107voidRunchild()8{9int cnt =5;10while(cnt)11{12printf("child pid:%d ,ppid%d\n",getpid(),getppid());13sleep(1);14     cnt--;15}16}17intmain()18{//创建多进程19for(int i =0; i < N ;i ++)20{21     pid_t id  =fork();22if( id ==0)23{24//子进程25Runchild();26exit(i);27}28//父进程 29printf("create child process: %d success\n", id);30}31//  sleep(10);32//多进程等待33for(int i =0; i < N  ; i++)34{35//      pid_t id   =  wait(NULL);36int status =0;37     pid_t id=waitpid(-1,&status ,0);3839if( id>0)40{41printf("wait %d success,exit code:%d\n", id,WEXITSTATUS(status ));//id ,退出码42}4344}4546sleep(5);108return0;109}

options:
1、options为0时,父进程阻塞等待
2、options为WNOHANG时,若等待的子进程没有结束,则waitpid函数直接返回0,不予以等待。若正常结束,则返回该子进程的pid

非阻塞轮询
options为WNOHANG时,父进程等待子进程中实现非阻塞

例如,父进程可以隔一段时间调用一次waitpid函数,若是等待的子进程尚未退出,则父进程可以先去做一些其他事,过一段时间再调用waitpid函数读取子进程的退出信息。

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107voidRunchild()8{9int cnt =5;10while(cnt)11{12printf("child pid:%d ,ppid%d\n",getpid(),getppid());13sleep(1);14     cnt--;15}16}17intmain()18{48  pid_t id =fork();49if(id <0)50{51perror("fork");52return1;53}54elseif( id ==0)55{56//child 5758int cnt =3;59while(cnt)60{61printf("I am a child ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);62     cnt --;63sleep(1);64}65exit(11);66}67else// parent 68{78int status =0;//输出型参数79//操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中80while(1)//轮询81{8283   pid_t  ret =waitpid( id,&status , WNOHANG );//非阻塞等待8485//等待成功86if( ret >0)//id是子进程的pid87{88//status存放的是子进程的退出信息89//7F 0111 1111 90//0xFF91// printf("wait success,ret:%d, exit sig : %d, exit code:%d\n", ret, status&0x7F , (status>>8) &0xFF  ); //打印的分别是 id, 信号, 退出码9293if(WEXITSTATUS(status))94{95printf("进程是正常跑完的,退出码:%d\n",WEXITSTATUS(status));96}97else98{99printf("进程出异常了\n");100}101break;102}103elseif( ret<0)104{105printf("wait failed\n");106break;107}108else//ret==0109{110printf("子进程还没有退出我再等等\n");111sleep(1);112}113}114sleep(3);115116117}118return0;119}

在这里插入图片描述

WNOHANG:
非阻塞等待:
1、如果子进程已经退出,waitpid成功返回
2、如果子进程没有退出,并且等待期间没有异常,waitpid检测完子进程,发现子进程没有退出,waitpid立马返回0

非阻塞轮询 +父进程做自己的事情

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6 #define N 107 #define TASK_NUM 1018typedefvoid(*task_t )();//函数指针1920 task_t  tasks[TASK_NUM];21222324intAddTask(task_t t );29voidtask1()30{31printf("这是一个执行打印日志的任务\n");32}33voidtask2()34{35printf("这是一个执行检测网络健康状态的任务\n");36}37voidtask3()38{39printf("这是一个进行绘制图形界面的任务\n");40}41voidInitTask()42{43int i =0;44for(; i< TASK_NUM ; i++)45{46     tasks[i]=NULL;47}48AddTask(task1);49AddTask(task2 );50AddTask(task3);51}5253intAddTask( task_t t    )54{55//找到数组中为空的位置56int i =0;57for(; i< TASK_NUM ; i++)58{59if( tasks[i]==NULL)60{61break;62}63}64if( i == TASK_NUM  )65{66return-1;67}68   tasks[i]=t ;//放任务6970return0;72}76voidExecuteTask()77{78int i =0;79for(; i<TASK_NUM ; i++)80{81//如果为空 ,继续走82if( tasks[i]==NULL)83{84continue;85}86//不为空87     tasks[i]();88}89}92intmain()93{123  pid_t id =fork();124if(id <0)125{126perror("fork");127return1;128}129elseif( id ==0)130{131//child 133int cnt =5;134while(cnt)135{136printf("I am a child ,pid:%d , ppid:%d cnt: %d\n",getpid(),getppid(),cnt);137     cnt --;138sleep(1);139}140exit(11);141}142else// parent 143{153int status =0;//输出型参数154//操作系统会去找对应id的子进程,并且等待该子进程,如果该子进程退出 ,操作系统会将子进程的退出信息拷贝到status指针所指向的变量当中155InitTask();156while(1)//轮询157{159   pid_t  ret =waitpid( id,&status , WNOHANG );//非阻塞等待161//等待成功162if( ret >0)//id是子进程的pid163{164//status存放的是子进程的退出信息165//7F 0111 1111 166//0xFF167// printf("wait success,ret:%d, exit sig : %d, exit code:%d\n", ret, status&0x7F , (status>>8) &0xFF  ); //打印的分别是 id, 信>    号, 退出码168169if(WEXITSTATUS(status))170{171printf("进程是正常跑完的,退出码:%d\n",WEXITSTATUS(status));172}173else174{175printf("进程出异常了\n");176}177break;178}179elseif( ret<0)180{181printf("wait failed\n");182break;183}184else//ret==0185{189ExecuteTask();190usleep(500000);191}192}193sleep(3);196}197return0;198}

在这里插入图片描述

父进程并不需要立马回收子进程,可以延迟一点时间回收子进程
如果有很多子进程,这些进程的退出时间比较集中,此时父进程统一进行回收反而更好

父进程将所有的子进程创建出来,由父进程对创建的子进程进行退出 ,正常情况下,父进程是最后一个退出的进程

替换原理

execl

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4intmain()5{6printf(" before : I am a process , pid %d , ppid %d\n",getpid(),getppid());78//最后一个参数必须是NULL                                                                                             9execl("/usr/bin/ls","ls","-a","-l",NULL);1011printf(" after : I am a process , pid %d , ppid %d\n",getpid(),getppid());12return0;13}

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

程序替换:
用ls的代码替换自己的代码,用ls的数据替换自己的数据
一旦替换完成之后,只需要将页表的物理地址修改
然后,从0开始执行

进行进程程序替换时,有没有创建新的进程?
不创建新进程,只进行进程的程序代码和数据的替换工作
我自己程序在运行的时候,当运行到程序替换的位置时,可执行程序用execl加载时,execl用新程序的代码替换老程序的代码,用新程序的数据替换老程序的数据,让CPU执行新程序的入口地址,整个过程中,只把当前进程的代码和数据进行替换,并没有更改当前进程,没有创建新进程

再看下面的代码

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6intmain()7{8   pid_t id =fork();9if(id ==0)10{11//child 1213printf(" before : I am a process , pid %d , ppid %d\n",getpid(),getppid());14sleep(5);15//最后一个参数必须是NULL16execl("/usr/bin/ls","ls","-a","-l",NULL);17printf(" after : I am a process , pid %d , ppid %d\n",getpid(),getppid());18exit(0);19}20//father                                                                                                                          21   pid_t ret =waitpid(id ,NULL,0);22if(ret >0)23{24printf("wait success, father pid :%d  , ret id:%d\n",getpid(), ret);25}26sleep(5);27return0;28}

在这里插入图片描述

子进程在没有执行execl,子进程的代码和数据是父进程的代码和数据
当子进程在在执行execl,把ls的代码替换进来时,替换数据时发生写时拷贝

程序替换成功之后,exec类型的函数后续的代码不会被执行,
如果替换失败 ,才可能执行后续代码
exec类型的函数,只有失败有返回值,函数执行成功,无返回值

程序加载到内存中 ,CPU如何得知程序的入口地址?
Linux中形成的可执行程序,是ELF格式,可执行程序在最开始有表头,可执行程序的入口地址就在表中,程序加载到内存中,可以不将代码和数据加载到内存,但是一定要将表头加载到内存中

execl

替换函数有六种以exec开头的函数,它们统称为exec函数

在这里插入图片描述
第一个参数是要执行程序的路径(绝对路径或者相对路径),第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾

//最后一个参数必须是NULLexecl("/usr/bin/ls","ls","-a","-l",NULL);

execlp

在这里插入图片描述
execlp中的p , p是PATH,表示 execlp函数自己会在默认的PATH环境变量中查找
第一个参数不用带可执行程序的路径(绝对路径或者相对路径),execlp自己会去PATH环境变量中去找可执行程序所对应的路径

第一个参数是要执行程序的名字,第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾

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

execv

在这里插入图片描述
execv中的 v ,可以理解为vector

第一个参数是要执行程序的路径(绝对路径或者相对路径),第二个参数是一个指针数组,数组当中的内容表示你要如何执行这个程序,数组以NULL结尾

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

在命令行中,所有的进程都是Bash的子进程,所有的进程在启动时都是采用exec系列函数来启动执行的 ,exec系列函数承担着加载器的效果,把可执行程序导到内存中

execvp

execvp中的p , p是PATH,表示 execvp函数自己会在默认的PATH环境变量中查找
execvp中的 v ,可以理解为vector

第一个参数不用带可执行程序的路径(绝对路径或者相对路径),execvp自己会去PATH环境变量中去找可执行程序所对应的路径
第一个参数是要执行程序的名字,第二个参数是一个指针数组,数组当中的内容表示你要如何执行这个程序,数组以NULL结尾
在这里插入图片描述

char*const myargv[]={"ls","-l","-a",NULL};execvp("ls", myargv );

execle

在这里插入图片描述

execle 中的e 是env环境变量

Makefile形成两个可执行程序

1.PHONY:all
  2 all:otherExe mycommand
  34 otherExe:otherExe.cpp
  5   g++-o $@ $^-std=c++116 mycommand :mycommand.c
  7   gcc -o $@ $^-std=c99
  8.PHONY:clean
  9 clean:10     rm -rf mycommand otherExe

用c语言去调用c++形成的可执行程序
在这里插入图片描述

1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 #include<sys/types.h>5 #include<sys/wait.h>6intmain()7{8   pid_t id =fork();9if(id ==0)10{11//child 13printf(" before : I am a process , pid %d , ppid %d\n",getpid(),getppid());22execl("./otherExe","otherExe",NULL);23printf(" after : I am a process , pid %d , ppid %d\n",getpid(),getppid());24exit(1);25}26//father 27   pid_t ret =waitpid(id ,NULL,0);28if(ret >0)29{30printf("wait success, father pid :%d  , ret id:%d\n",getpid(), ret);31}32sleep(5);33return0;34}

无论是我们的可执行程序,还是脚本,为什么能跨语言调用?
所有语言运行起来,本质都是进程

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

在这里插入图片描述

在mycommand.c中execv函数 ,我们没有传环境变量的参数 ,为什么能打印出环境变量
环境变量是什么时候给进程的?
环境变量也是数据,创建子进程的时候,环境变量就已经被子进程继承下去了

在程序替换中,环境变量信息,不会被替换

如果想给子进程传递环境变量,该怎么传递?

1、新增环境变量:父进程的地址空间中直接putenv

putenv("PRIVALUE_ENV=66666");

在这里插入图片描述

execle

在这里插入图片描述
第一个参数是要执行程序的路径(绝对路径或者相对路径),第二个参数是可变参数列表,表示你要如何执行这个程序,并以NULL结尾,第三个参数是你自己设置的环境变量。

例如,你设置了PRIVALUE_ENV环境变量,在mycommand程序内部就可以使用该环境变量。

externchar** environ;execle("./otherExe ","otherExe","-a","-w","-v",NULL,environ );

覆盖之前的环境变量

char*const myenv[]={"MYVAL=1111","MYPATH=/usr/bin/xxx",NULL};execle("./otherExe","otherExe","-a","-w","-v",NULL,myenv );

在这里插入图片描述

在这里插入图片描述

如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注你们的每一次支持都将转化为我前进的动力!!!

标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/qq_73478334/article/details/138303774
版权归原作者 鄃鳕 所有, 如有侵权,请联系我们删除。

“进程控制【Linux】”的评论:

还没有评论