
图控大叔
构图传递思想
阅读从未如此简单!!!
01
前言
在进程的开发中,我们常常需要创建子进程来实现进程的“分身”,但是子进程执行完任务之后,需要父进程对其进行资源回收,否则该子进程将变成僵尸进程。那么父进程对子进程的资源回收所用到的函数则有我们今天的主角:wait和waitpid。
02
函数讲解

wait函数
需要包含头文件
#include
#include
函数原型
pid_t wait (int * status);
参数说明:
1、如果父进程需要知道子进程结束时候的状态值.则可以填充参数
如:
int status;
//创建子进程及相应判断
printf("wait(&status) is %d\n",wait(&status));
2、如果父进程不需要知道子进程结束时候的状态值.则可以填充NULL
如:
int status;
//创建子进程及相应判断
printf("wait(NULL) is %d\n",wait(NULL));
返回值
1、 -1 ---》该子进程不存在
2、 子进程pid
其他说明
1、wait函数的调用暂时停止目前进程的执行, 直到有信号来到或子进程结束
2、如果同时创建了多个子进程,并且这些子进程都有调用退出函数,如:exit
哪个子进程先介绍,wait就先返回哪个子进程的pid值
(小编做了好多次测试,发现都是其他一样效果,后来在老师的指导下才纠正了这个思维定式的问题)

waitpid函数
需包含头文件
#include
#include
函数原型
pid_t waitpid(pid_t pid, int * status, int options);
参数说明:
pid:
pid<-1 等待进程组识别码为 pid 绝对值的任何子进程.
pid=-1 等待任何子进程, 相当于 wait().
pid=0 等待进程组识别码与目前进程相同的任何子进程. (和wait()一样)
pid>0 等待任何子进程识别码为 pid 的子进程.
说明:pid 乱填,该进程组内没有此pid的子进程,会返回-1
status:
用法和wait一样
options:
一般填0,有以下其他种选择,小编还没有弄懂,以后弄懂了再补充
其他选择为:
WNOHANG
如果没有任何已经结束的子进程则马上返回, 不予以等待.
WUNTRACED
如果子进程进入暂停执行情况则马上返回, 但结束状态不予以理会.
子进程的结束状态返回后存于 status, 底下有几个宏可判别结束情况
WIFEXITED(status)
如果子进程正常结束则为非 0 值.
WEXITSTATUS(status)
取得子进程 exit()返回的结束代码,
一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏.
WIFSIGNALED(status)
如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)
取得子进程因信号而中止的信号代码, 一般会先用 WIFSIGNALED 来判断后才使用此宏.
WIFSTOPPED(status)
如果子进程处于暂停执行情况则此宏值为真. 一般只有使用 WUNTRACED 时才会有此情况.
WSTOPSIG(status)
取得引发子进程暂停的信号代码, 一般会先用 WIFSTOPPED 来判断后才使用此宏.
返回值:
和wait一样。
其他说明:
waitpid
1、如果所填pid所对应子进程不存在,则立即返回-1
2、如果所填pid存在,但是一直不退出,则一直等待
该子进程不退出为可能
1、调用了pause()
2、vfork函数创建的子进程未调用exit
因为fork函数创建的子进程调用return或者exit都可以退出
3、一直处于while循环中
4、还有其他情况,小编可能不知道

图片补充
03
代码

#include
#include
int main(int argc,const char **argv){
pid_t cpid[2];
int status;
cpid[0] = fork();
if(cpid[0] == -1)
{
perror("进程1创建失败\n");
return -1;
}
else if(cpid[0]==0)
{
printf("client1 id %d father id %d\n",getpid(),getppid());
//sleep(0);
//pause();
exit(0);
}
cpid[1] = fork();
//printf("开始 2\n");
if(cpid[1] == -1)
{
perror("进程2创建失败\n");
return -1;
}
if(cpid[1]==0)
{
printf("client2 id %d father id %d\n",getpid(),getppid());
//sleep(2);
//pause();
//return 0;
exit(0);
}
else{
//wait(&status);
//printf("wait is %d\n",wait(&status));//首先结束第一个创建的子程序
//printf("wait is %d\n",wait(&status));
//printf("wait(&status) is %d\n",wait(&status));
printf("wait is %d\n",waitpid(cpid[1],&status,WIFEXITED(status)));
//printf("wait cpid[1] %d is %d\n",cpid[1],waitpid(cpid[1],&status,0));
printf("father id is %d\n",getpid());
}
return 0;
}
04
留个问题
exit函数让调用者所对应进程结束,那么exit函数有负责进程资源的回收吗?答案是没有。exit和wait有什么不一样?当然有,自己总结!
05
结尾
本次关于Linux环境下子进程内存资源的回收所涉及的部分函数:wait和waitpid就分享到这里,如有纰漏,希望不吝赐教!谢谢阅读!