热点资讯

你的位置:开发旅游小程序的公司 > 小程序开发公司资讯价格 > 小程序开发 Linux系统编程之waitpid函数详解_linux waitpid

小程序开发 Linux系统编程之waitpid函数详解_linux waitpid


发布日期:2024-09-28 13:25    点击次数:128


5.1 为什么要进行程度资源的回收小程序开发

        当一个子程度退出之后,该程度大略回收我方的用户区的资源,然而不成回收内核空间区的PCB(process control block 程度放肆块)资源。

(即:子程度我方自身是无法完成对内核的PCB资源的回收,此时就会相押店张linux系统的资源了!)

        这个子程度内核区的PCB资源必须得由它的父程度,调用wait 或者 waitpid函数完成对其子程度的回收,从而幸免了对系统资源的铺张!

图片小程序开发

5.2 孤儿程度

(自身不是误差!因为孤儿程度照旧不错存谢世的,不错给init程度回收其内核区的PCB资源的,一切齐照旧常常的/可罗致的case)

        孤儿程度的主见:

        若子程度的父程度照旧死掉(先于子程度实践退出),而子程度还谢世,那么这个子程度此时就会形成孤儿程度了!

        (在Linux操作系统下,是必须要保证每一个程度齐有一个父程度的)为了保证每个程度齐有一个父程度,孤儿程度会被一个程度id PID==1的叫作念init的程度回收掉(领养),那么init程度就成为了该孤儿程度的养父程度了。当孤儿程度实践退出之后,由init程度完成对孤儿程度资源的回收。

上期开出奇偶比3:2,近10期奇偶比为26:24,本期前区推荐奇偶比1:4。

上期龙头开出奇数球05,近10期龙头开出07 04 06 04 05 02 08 01 01 05,奇偶比5:5,本期参考奇数球05。

图片

        模拟孤儿程度的案例: 

        编写模拟孤儿程度的代码,并考证孤儿程度的父程度是否由原本的父程度变为init程度。

test codes1:

//测试代码,测试父程度先死掉(先实践退出)后,是否由于PID==1的init程度把该子程度领养了!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	//创建子程度函数原型:	//pid_t fork(void);	pid_t pid = fork();	if(pid < 0)//fork失败的case	{		perror("fork error!");		return -1;	}	else if(pid == 0)//pid == 0 时,则面前景度为子程度	{		printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());	}	else//pid > 0 时,则面前景度为父程度	{ 		//pid_t getpid(void);		//这个函数会复返调用该函数的程度的ID		//(哪个程度调用它,它就复返谁的PID)		printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());		sleep(2);//让父程度后退出,此时就不会出现孤女儿程度的case了!	}	return 0;}

result1:

 

图片

 

此时属于常常case,不会出现僵尸子程度的case! (因为其父程度sleep了2s,等子程度先终了)

补充:

        pid_t getpid(void);

        这个函数会复返调用该函数的程度的ID

        (哪个程度调用它,它就复返谁的PID)

        pid_t getppid(void);

        这个函数会复返调用该函数的程度的父程度的ID

        (哪个子程度调用它,它就复返它的父程度的PID)

 test codes2:

//测试代码,测试父程度先死掉(先实践退出)后,是否由于PID==1的init程度把该子程度领养了!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<string.h>#include<stdlib.h>int main(){	//创建子程度函数原型:	//pid_t fork(void);	pid_t pid = fork();	if(pid < 0)//fork失败的case	{		perror("fork error!");		return -1;	}	else if(pid == 0)//pid == 0 时,则面前景度为子程度	{		printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());	}	else//pid > 0 时,则面前景度为父程度	{ 		//pid_t getpid(void);		//这个函数会复返调用该函数的程度的ID		//(哪个程度调用它,它就复返谁的PID)		printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());	}	return 0;}

result2:

图片

图片

小追溯:

        孤儿程度:当父程度先退出,子程度后退出时,子程度就形成孤儿程度了,此时由init程度(PID==1)回收。当子程度也退出之后(他我方会回收我方用户区的资源),而init程度则会回收养子程度的内核区PCB资源。

5.3 僵尸程度(在开荒阵势时,一定要小心僵尸程度的问题!不要给我写出)

(自身即是个误差!因为僵尸程度是照旧死掉了的,要是不杀死其原父程度---给init程度回收其内核区的PCB资源的话,此时系统就一直无法回收其内核区PCB资源,这么朝夕你的系统资源给破钞掉,破钞收场你的系统就无法再创建新的程度了。一朝系统无法创建新的程度,这将会是很可怕的事情!此时即是不常常的/不可罗致的case)

        僵尸程度的主见:

        若子程度死了,父程度还谢世,然而父程度莫得调用wait 或者 waitpid函数完成春联程度的回收时(或者说父程度调用waitpid函数对其子程度进行回收时,子程度还谢世,且waitpid函数的options==WNOHANG非防碍的),此时的子程度就形成僵尸程度。

(当当子程度先退出,而父程度莫得完成春联程度资源的回收,此时的子程度就会形成僵尸程度!)

        补充:在ps ajx敕令下,你不错看到所干系于程度的信息,此时,假定某父程度名字为zombie,若你还看到有[zombie]<defunct>这么的程度,就说明此时你的系统存在着僵尸程度!<defunct>这个关键字就标志了这个程度为僵尸程度!因为defunct是adj,灭绝的,不存在的真义!

        如何惩处 僵尸程度(不回收导致的系统资源铺张)的问题呢?

        答:

        临时的非最好的惩处方法是:要念念把僵尸程度的资源立时给回收掉,需要你通过使用kill -9 pid敕令,平直杀掉其对应的父程度(因为僵尸子程度照旧是个死掉了的程度,它没法罗致并复兴你给它传的kill -9 僵尸子程度pid这么的杀死我方的敕令)。

        原因:杀死僵尸子程度的原父程度,不错让该僵尸子程度给init程度领养,由init程度来do回收它的资源的责任。这就不错幸免僵尸子程度的资源莫得被回收而导致的系统资源的铺张!

        最好的最好的惩处方法是:在子程度先于父程度退出后,让父程度调用wait或者waitpid函数对其资源进行回收!(这个背面学到wait以及waitpid函数时就会讲到!底下先对临时的惩处方法写一个代码do考证测试!)

        模拟僵尸程度的案例:

        编写模拟僵尸程度的代码,考证若子程度先于父程度退出,而父程度又莫得调用wait或者waitpid函数对其程度内核区PCB资源的回收,从而是的子程度形成了僵尸程度。

test codes:

//测试代码,测试子程度先死掉(先实践退出)后,父程度莫得回收子程度的资源//此时的子程度就会形成僵尸程度了!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	//创建子程度函数原型:	//pid_t fork(void);	pid_t pid = fork();//fork开一个子程度!	if(pid < 0)//fork失败的case	{		perror("fork error!");		return -1;	}	else if(pid == 0)//pid == 0 时,则面前景度为子程度	{		printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());	}	else//pid > 0 时,则面前景度为父程度	{ 		sleep(200);//父程度寝息100s		//让父程度后退出,此时就不会出现孤女儿程度的case!		//然而,此时就会出现子程度资源莫得被父程度回收的case!		//因此,此时的子程度就会形成僵尸程度!		printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());	}	return 0;}

result:

图片

输入敕令ps ajx后:

图片

注:这个[zombie]<defunct>就代表了僵尸子程度!因为子程度的用户区(包含称呼等的信息)是由父程度copy已往的,统统子程度的名字和父程度的名字是同样的!(这个小点是你必须要care的 !必须要小心的!)

输入敕令kill -9 1835252(尝试kill掉僵尸子程度)且 输入敕令ps ajx后:

图片

图片

这说明,联系我们僵尸程度照旧死掉了,你没法用活的kill -9敕令去删除它!

那么咱们如何让该僵尸程度给立时回收呢?

答:平直杀死该僵尸子程度的父程度,然后该僵尸程度立时就给init程度领养了,领养之后由init程度把这个僵尸程度的资源回收掉!

kill 僵尸程度的父程度 且 输入敕令ps ajx后:

图片

图片

        惩处上述僵尸程度问题的最好决策:在子程度先于父程度退出后,立时让父程度调用wait或者waitpid函数对其进行资源的回收责任!

        因此,底下咱们将学习wait以及waitpid这两个程度回收函数!

5.4 程度回收函数

无论是wait/waitpid函数,齐是在父程度中调用该函数以完成对其子程度资源的回收责任的!

       ①wait函数(是在父程度中调用该函数以完成对其子程度资源的回收责任)

                函数原型:

                pid_t wait(int* wstatus);

                //若不怜惜程度的终了景况(终了原因)时,不错传NULL进去!

                函数作用:

                        1-- 防碍并恭候子程度退出

                        (小心:这是个防碍函数!一直防碍,比及子程度退出后该函数才调复返!)

                        2-- (由父程度)回收子程度残留资源

                        3-- 取得子程度终了景况(退出原因)

                函数复返值:

                        if得胜:计帐掉子程度ID;

                        if失败:复返-1(示意子程度充足回收掉了,没得子程度回收了)

                wstatus 参数(不错通过man 2 wait敕令查询):子程度的退出景况 -- 传出参数

(唯有你不传NULL的wstatus进去,后续需要使用wstatus参数来写代码了解子程度退出的景况的,不然,你压根就无需使用wstatus参数的写代码了)

        (这些宏参数,不需要你记着!你只需要会查阅,找到使用方法即可!)

                        WIFEXITED(wstatus):为非0 -> 程度常常终了

图片

                        WEXITSTATUS(wstatus):取得程度退出景况

图片

                        WIFSIGNALED(wstatus):为非0 -> 程度特殊拒绝(此时程度时被信号signal杀死的,比如kill -9 pid信号)

图片

                        WTERMSIG(wstatus):取得 使程度拒绝的信号的编号

图片

wait 函数训练案例:

test codes1:

//wait函数测试代码,测试让父程度调用wait函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>//这个头文献不错 在 man 2 wait中看到!#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	//轮回创建3个子程度	for(i = 0;i<3;++i){		pid_t pid = fork();//创建子程度		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid == 0){// 子程度			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(2);//让子程度寝息2s,以阐发其父程度中的wait函数照实是防碍函数!			break;//这个break就保证了所创建的程度均为兄弟程度!		}		else //pid > 0 父程度		{			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			pid_t exit_pid = wait(NULL);//wait函数会防碍恭候子程度退出后,将其回收!			if(exit_pid == -1){				printf("There is no child process already!");				break;			}			printf("wait函数得胜复返!\nexit_pid==child_pid==[%d]\n",exit_pid);		}		printf("\n");	}	return 0;}

result1:

图片

 test codes2:

//wait函数测试代码,测试让父程度调用wait函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	//轮回创建3个子程度	for(i = 0;i<2;++i){		pid_t pid = fork();//创建子程度		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid == 0){// 子程度			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(2);			break;//这个break就保证了所创建的程度均为兄弟程度!		}		else //pid > 0 父程度		{			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			int wstatus = -1;			pid_t exit_wait_pid = wait(&wstatus);//wait函数会防碍恭候子程度退出后,将其回收!			if(exit_wait_pid == -1){				printf("There is no child process already!");				break;			}			if(WIFEXITED(wstatus)){//if WIFEXITED(wstatus) == true 子程度常常退出				printf("子程度 常常退出!\n");				//WEXITSTATUS(wstatus));复返子程度退出的景况(原因)				printf("子程度退出的景况(原因):%d\n",WEXITSTATUS(wstatus));			}			else if(WIFSIGNALED(wstatus)){//if WIFSIGNALED(wstatus) == true 子程度是被信号杀死而退出的!				int sigNumber = WTERMSIG(wstatus);//WTERMSIG(wstatus);复返杀死子程度的信号number				printf("子程度 由信号 signal[%d] 杀死了!\n",sigNumber);			}			printf("wait函数得胜复返!\nexit_wait_pid==child_pid==[%d]\n",exit_wait_pid);		}		printf("\n");	}	return 0;}

 result2:

图片

test codes3:

app
//wait函数测试代码,测试让父程度调用wait函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	//轮回创建3个子程度	for(i = 0;i<2;++i){		pid_t pid = fork();//创建子程度		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid == 0){// 子程度			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(200);			break;//这个break就保证了所创建的程度均为兄弟程度!		}		else //pid > 0 父程度		{			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			int wstatus = -1;			pid_t exit_wait_pid = wait(&wstatus);//wait函数会防碍恭候子程度退出后,将其回收!			if(exit_wait_pid == -1){				printf("There is no child process already!");				break;			}			if(WIFEXITED(wstatus)){//if WIFEXITED(wstatus) == true 子程度常常退出				printf("子程度 常常退出!\n");				//WEXITSTATUS(wstatus));复返子程度退出的景况(原因)				printf("子程度退出的景况(原因):%d\n",WEXITSTATUS(wstatus));			}			else if(WIFSIGNALED(wstatus)){//if WIFSIGNALED(wstatus) == true 子程度是被信号杀死而退出的!				int sigNumber = WTERMSIG(wstatus);//WTERMSIG(wstatus);复返杀死子程度的信号number				printf("子程度 由信号 signal[%d] 杀死了!\n",sigNumber);			}			printf("wait函数得胜复返!\nexit_wait_pid==child_pid==[%d]\n",exit_wait_pid);		}		printf("\n");	}	return 0;}

result3:(演示用kill -9 pid 敕令杀死子程度的wait函数的复返景况的后果)

图片

 

图片

 wait函数小追溯:

        pid_t wait(int* wstatus);

        注:若春联程度的退出景况不感兴味的话,不错平直传NULL进去即可!

        参数:

        wstatus:子程度的退出景况

if(WIFEXITED(wstatus)){    WEXITSTATUS(wstatus)}else if(WIFSIGNALED(wstatus)){    WTERMSIG(wstatus)}

        ②waitpid函数(比wait函数更高等,功能也愈加雄壮,亦然在父程度中调用该函数以完成对其子程度资源的回收责任)

                函数原型:

                pid_t waitpid(pid_t pid,int* wstatus,int options);

                注:这个waitpid函数默许case下即是防碍的函数!

                函数作用:(同wait函数)

                        1-- 防碍并恭候子程度退出

                        (小心:这亦然个防碍函数!一直防碍,比及子程度退出后该函数才调复返!)

                        2-- (由父程度)回收子程度残留资源

                        3-- 取得子程度终了景况(退出原因)

                函数参数:

                pid参数:

                        1-- 当pid == -1时 恭候任一子程度。与wait等效(多用)    

                        (东说念主话:即是回收统统(多个)的子程度)

(固然,父程度每调用一次的waitpid函数就只大略回收一个子程度辛劳,一次该函数的调用并不成回收多个子程度!)

                        2-- 当pid > 0时 恭候其程度ID 与 pid 极度的子程度(多用)    

                        (东说念主话:即是回收指定(一个)PID的子程度)

                        3-- 当pid == 0时 恭候程度组ID 与 当今程度磋商的任何子程度。(少用/基本无须)     

                        (东说念主话:回收任何和调用waitpid()函数的父程度在合并个程度组内部的统统程。)

                        (程度齐是有所属组的)

                        4-- 当pid < -1时 恭候其组ID 等于 pid的彻底值得任一子程度。(少用/基本无须)   

                        (东说念主话:回收在其他组的子程度)

                wstatus 参数(不错通过man 2 wait敕令查询):子程度的退出景况 -- 传出参数 用法同wait函数。

(唯有你不传NULL的wstatus进去,后续需要使用wstatus参数来写代码了解子程度退出的景况的,不然,你压根就无需使用wstatus参数的写代码了)

        (这些宏参数,不需要你记着!你只需要会查阅,找到使用方法即可!)

                       WIFEXITED(wstatus):为非0 -> 程度常常终了

图片

                        WEXITSTATUS(wstatus):取得程度退出景况

图片

                        WIFSIGNALED(wstatus):为非0 -> 程度特殊拒绝(此时程度时被信号signal杀死的,比如kill -9 pid信号)

图片

                        WTERMSIG(wstatus):取得 使程度拒绝的信号的编号

图片

                options参数:

                        1-- 诞生为options  == 0,示意waitpid函数为防碍的。(该函数会防碍卡在这儿,若有子程度,就回收;若莫得子程度,一直卡着)

                        2-- 诞生为options == WNOHANG,示意waitpid函数为非防碍的(也即非论有莫得子程度了,该函数齐不会防碍卡在这儿)

                        (时常,当你念念把waitpid函数诞生为非防碍的时刻(即让该函数不影响别的要领的实践,别仅仅卡在这儿),就让options == WNOHANG)

图片

                函数复返值:

                 >0:示意复返的是回收掉的子程度ID(PID);

                  -1:示意无子程度了;(示意子程度充足回收掉了,没得子程度回收了)

                 =0 且 第3个参数options为WNOHANG时:示意子程度正在启动(子程度尚未退出);

在linux的终局下输入man 2 waitpid/wait敕令可查询到:

图片

                waitpid函数案例训练:

test codes1:

//waitpid函数测试代码,测试让父程度调用waitpid函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	for(;i<3;++i){		//轮回创建3个子程度		pid_t pid = fork();		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid==0){//面前景度为 子程度			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(2);			break;//这个break语句会保证所创建的子程度齐为兄弟子程度		}		else{//pid > 0 面前景度为 父程度			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			//在父程度中调用waitpid函数!			pid_t inputPid = -1;//inputPid==-1示意我要回收面前统统的子程度            //即恭候着任一子程度do回收的真义			int* wstatus = NULL;//status == NULL示意我不怜惜子程度的退出景况			int options = 0;//options==0示意该函数是防碍的			pid_t exit_waitpid_pid = waitpid(inputPid,wstatus,options);			if(exit_waitpid_pid > 0){//示意得胜回收掉子程度了!				printf("得胜回收掉子程度了,此时所回收掉的子程度id==[%d]\n",exit_waitpid_pid);			}			else if(exit_waitpid_pid == -1){				printf("面前莫得需要回收掉的子程度了!\n");			}			else if(exit_waitpid_pid == 0 && options == WNOHANG){				printf("面前需要回收的子程度还在启动中,尚未退出!\n");			}		}		printf("\n");	}	return 0;}

result1:

图片

test codes2:

//waitpid函数测试代码,测试让父程度调用waitpid函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	for(;i<3;++i){		//轮回创建3个子程度		pid_t pid = fork();		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid==0){//面前景度为 子程度			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(2);			break;//这个break语句会保证所创建的子程度齐为兄弟子程度		}		else{//pid > 0 面前景度为 父程度			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			//在父程度中调用waitpid函数!			pid_t inputPid = -1;//inputPid==-1示意我要回收面前统统的子程度			int wstatus = -1;//&status != NULL示意我怜惜子程度的退出景况								//后续需要衔尾wstatus的参数写代码了解子程度的退出景况			int options = WNOHANG;//options==WNOHANG示意该函数是不防碍的			pid_t exit_waitpid_pid = waitpid(pid,&wstatus,options);			if(exit_waitpid_pid > 0){//示意得胜回收掉子程度了!				printf("得胜回收掉子程度了,此时所回收掉的子程度id==[%d]\n",exit_waitpid_pid);				//得胜回收掉子程度,才调够判断其退出景况!				if(WIFEXITED(wstatus)){					printf("子程度常常退出了!子程度的退出景况是:%d\n",WEXITSTATUS(wstatus));				}else if(WIFSIGNALED(wstatus)){					printf("子程度时由信号[%d]杀死的!\n",WTERMSIG(wstatus));				}			}			else if(exit_waitpid_pid == -1){				printf("面前莫得需要回收掉子程度了,即:谢世的子程度齐照旧死掉了退出了!\n");			}			else if(exit_waitpid_pid == 0 && options == WNOHANG){				printf("面前需要回收的子程度还在启动中,尚未退出!\n");			}			sleep(100);//让子程度形成僵尸程度!		}		printf("\n");	}	return 0;}

        阐扬:因为此刻,父程度调用waitpid函数对其子程度进行回收时,子程度还谢世,且waitpid函数的options==WNOHANG非防碍的),这么父程度又休息了100s,子程度才休息2s,因此子程度会先退出,此时父程度又没回收它的资源。因此,此时的子程度就形成僵尸程度了。 

result2:(这个test2代码会产生3个僵尸程度,这是所用waitpid的一个瑕疵,你不错用临时回收子程度的方法:平直杀掉其对应的原父程度!让init程度领养它,并对其资源进行回收,这么才调幸免铺张系统资源!)

图片

图片

 

图片

图片

图片

图片

然而,用临时回收子程度的方法照旧不太好的,因此咱们对test2这种,父程度调用非防碍的waitpid函数对其子程度回收时所遭遇的问题的代码,进行校阅,得到一份robust的代码!

技巧:一直轮回回收子程度的代码!知说念莫得子程度了/子程度齐给回收掉了!

so,底下这份代码是父程度调用非防碍式的waitpid函数对其子程度do回收责任的递次代码范本:

test codes3:

//waitpid函数测试代码,测试让父程度调用waitpid函数回收子程度资源!#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){	printf("before fork: pid==[%d]\n",getpid());	int i = 0;	for(;i<3;++i){		//轮回创建3个子程度		pid_t pid = fork();		if(pid < 0){			perror("fork error!");			return -1;		}		else if(pid==0){//面前景度为 子程度			printf("\n");			printf("第[%d]个子程度被父程度do轮回回收责任:",i+1);			printf("child process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			sleep(1);			break;//这个break语句会保证所创建的子程度齐为兄弟子程度		}		else{//pid > 0 面前景度为 父程度			printf("father process: pid==[%d],fpid==[%d]\n",getpid(),getppid());			//在父程度中调用waitpid函数!			while(1){				//这个while轮回,就照旧不错保证 父程度一定是晚于子程度退出的了!				pid_t inputPid = -1;//inputPid==-1示意我要回收面前统统的子程度				int wstatus = -1;//&status != NULL示意我怜惜子程度的退出景况									//后续需要衔尾wstatus的参数写代码了解子程度的退出景况				int options = WNOHANG;//options==WNOHANG示意该函数是不防碍的				pid_t exit_waitpid_pid = waitpid(pid,&wstatus,options);				if(exit_waitpid_pid > 0){//示意得胜回收掉子程度了!					printf("得胜回收掉子程度了,此时所回收掉的子程度id==[%d]\n",exit_waitpid_pid);					//得胜回收掉子程度,才调够判断其退出景况!					if(WIFEXITED(wstatus)){						printf("子程度常常退出了!子程度的退出景况是:%d\n",WEXITSTATUS(wstatus));					}else if(WIFSIGNALED(wstatus)){						printf("子程度时由信号[%d]杀死的!\n",WTERMSIG(wstatus));					}				}				else if(exit_waitpid_pid == 0 && options == WNOHANG){					// printf("面前需要回收的子程度还在启动中,尚未退出!\n");					//因为这句子程度尚在启动的话笃定是大齐打印的!                    //so这些测试代码不错在测试要领时使用,然而在本色阵势中就凝视掉了吧!				}				else if(exit_waitpid_pid == -1){					printf("面前莫得需要回收掉子程度了,即:谢世的子程度齐照旧死掉了退出了!\n");					printf("此时,莫得需要回收掉子程度了,就平直break 退出轮回,无需再do回收子程度资源的责任了!\n");					break;//此时,莫得需要回收掉子程度了,就平直break 退出轮回,无需再do回收子程度资源的责任了!				}			}		}		printf("\n");	}	return 0;}

result3:

图片

waitpid函数小追溯:

waitpid函数:pid_t waitpid(pid_t pid,int* status,int options);    参数:        pid:            pid > 0:示意恭候指定的子程度            pid==-1:示意恭候任一子程度        status:        同wait函数        options:            0:示意防碍            WNOHANG:示意不防碍(无论有莫得子程度退出,waitpid函数齐会立时退出!不会防碍在这儿!)    复返值:        > 0:是回收掉子程度的PID        = 0:若options取值为WNOHANG,则示意子程度还谢世        -1:示意当今照旧莫得子程度了,此时那不错break掉轮回回收子程度的while轮回了!    小心:调用一次waitpid/wait函数只可回收一个子程度辛劳!灵魂拷问:为什么一定是由于父程度来调用wait/waitpid函数来对其子程度的资源进行回收呢?答:因为子程度无法对我方的内核区PCB的资源进行回收!这个程度放肆块的资源必须由其父程度去回收!一朝子程度先于父程度先退出,则此时的子程度就会形成僵尸程度!那么就会铺张系统资源!

小训练:

图片

图片

本站仅提供存储工作,统统内容均由用户发布,如发现存害或侵权内容,请点击举报。