当前位置:网站首页>进程控制:进程等待(回收子进程)
进程控制:进程等待(回收子进程)
2022-06-11 08:04:00 【小小酥诶】
进程等待的必要
当一个进程终止的时候,它的资源,比如说PCB,数据等不会被立马清理掉。它会保持在已经终止的状态,这种状态称为“僵尸状态”,直到被父进程确认。父进程wait,即父进程向内核确认子进程已经终止,可以为子进程“收尸”了,内核会把子进程的退出信息传给父进程,然后清理掉子进程的资源,这个时候子进程才算真正地终止了!
总结:
- 父进程等待,可以获取子进程的退出信息,知道子进程的执行结果。
- 父进程等待,可以释放子进程的资源,让子进程真正地退出,避免一直消耗系统的存储资源,造成“内存泄露”等危害。
- 父进程等待,可以保证时序的问题,子进程先于父进程退出,避免让子进程变为孤儿进程。
进程等待的方法
wait函数
一个进程可以通过调用wait函数等待子进程。wait函数是系统调用函数。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
返回值:返回被等待进程的pid,如果等待失败,返回-1。
参数:输出型参数,可以获取子进程的退出状态,如果不需要获取子进程的退出状态,则设置为NULL。
测试:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/wait.h>
5 #include <stdlib.h>
6
7 int main(void)
8 {
9 pid_t id = fork(); //创建子进程
10 if(id == 0)
11 {
12 //child
13 //执行5秒
14 int cnt = 5;
15 while(cnt)
16 {
17 printf("child[%d] , cnt:%d\n", getpid(), cnt);
18 sleep(1);
19 cnt--;
20 }
21 exit(EXIT_SUCCESS);
22 }
23 sleep(10);
24 pid_t ret = wait(NULL);
25 if(ret > 0)
26 {
27 //wait success, ret is pid;
28 printf("father wait child[%d] success\n", ret);
29 }
30 else{
31 //wait failed.
32 printf("father wait failed\n");
33 }
34 return 0;
35 }
现象:子进程执行5秒后,终止了,但是内核没有立马清理掉它的资源,所以此时是僵尸状态,再过了5秒之后,父进程休眠完毕,然后等待子进程,确认子进程已经终止,返回子进程的pid,然后内核开始清理子进程资源,子进程真正地终止了,又过了5秒后父进程也终止了。
通过wait函数的输出型参数可以获得子进程的退出信息。
waitpid函数
waitpid函数也可以使得父进程等待子进程
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
先不关心第二个和第三个参数,第二个参数可以设置为NULL,第三个参数暂时设置为0。
第一个参数:
1、如果第一个参数pid传的是某个具体的进程的进程ID,表示等待该指定进程
2、如果第一个参数pid传的是-1,表示等待父进程的任意子进程。
第三个参数:
- 传的是0,表示父进程是挂起等待子进程的(阻塞等待)。可以理解为“父进程在等待子进程的过程中,什么事情也没做,在干等”。
- 传的是宏WNOHANG,表示父进程是非阻塞等待。若等待的子进程还没有终止,那么waitpid函数立即返回0,不予以等待。若等待的子进程已经正常结束,那么waitpid函数返回等待子进程的PID
wait(&status) 等价于 waitpid(-1, &status, 0)
【注意事项】
- 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,获得子进程退出信息,并且释放被等待子进程资源。
- 如果在任意时刻调用wait/waitpid,子进程存在且还在正常运行,则父进程可能会发生阻塞。
- 如果试图等待一个当前不存在的进程,wait/waitpid会调用出错,并立即返回。
获取子进程退出信息
在上述并没有具体解释参数status的作用。
- 在wait和waitpid函数中,status的作用是一样的,它是输出型参数。
- 如果给status传的是NULL,则表示不需要获取子进程的退出信息。
- 如果给status传的是非NULL,则可以获取被等待进程的退出信息。
status是一个指向整形的指针。但是一个进程的退出信息那么多,怎么可能会那么简单地用一个整型就知道进程的退出信息了呢?实际上,并不是简单地看待status指向的整形,而是当作位图来看,一个整型有32位,这样就可以全面地描述被等待进程的退出信息了。
只用研究低16个比特位。
进程退出的情况有四种:
1、正常退出(自愿,代码执行完,结果正确)
2、错误退出(自愿,代码执行完,结果不正确)
3、异常退出(非自愿,代码未执行完,退出码无意义)
4、被其他进程终止(非自愿,代码未执行完,退出码无意义)
这四种情况,可以按照进程是否收到信号来分类,第一种和第二种进程未收到信号,第三和第四种进程收到信号。

当被等待进程不是被信号所终止时,低8位全是0,而次低8位则是被等待进程的退出码。
当被等待进程是被信号所终止时,低7位表示被等待进程收到的信号。
如果进程是正常终止,如何显示地知道退出码?
如果进程是收到信号而终止,如何知道它收到了什么信号?直接就是低7位表示的是进程收到的信号,如果是非法的信号,说明它没有收到信号,这个值是无效的。
测试:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/wait.h>
5 #include <stdlib.h>
6
7 int main(void)
8 {
9 pid_t id = fork(); //创建子进程
10 if(id == 0)
11 {
12 //child
13 //执行5秒
14 int cnt =7;
15 while(cnt)
16 {
17 printf("child[%d] , cnt:%d\n", getpid(), cnt);
18 sleep(1);
19 cnt--;
20 }
21 exit(12);
22 }
23 sleep(10);
24 int status;
25 pid_t ret = waitpid(id, &status, 0);
26 if(ret > 0)
27 {
28 //wait success, ret is pid;
29 printf("father wait child[%d] success\n", ret);
30 }
31 else{
32 //wait failed.
33 printf("father wait failed\n");
34 }
35 printf("get a exit num : %d\n, get a single:%d", (status >> 8) & 0XF FFF, status & 0XFFFF);
36 sleep(2);
37 return 0;
38 }

边栏推荐
- 2022.6.6 特长生模拟
- Tidb Cloud est en ligne sur le marché Google Cloud pour permettre aux développeurs du monde entier d'utiliser une nouvelle pile de bases de données htap en temps réel
- 【AtCoder2387】+/- Rectangle
- TypeScript-在koa中配置TS和使用koa-router
- How to do well in empty state design? Look at this comprehensive summary
- 2021-10-17
- Space geometry
- Detailed explanation of shift operator and bit operator in C language
- Dameng database login
- Dameng user management
猜你喜欢

Data visualization and Matplotlib

Servlet

SOCKET【5】- struct linger 用法

Figure seamless database integration tushare interface

Tidb Cloud est en ligne sur le marché Google Cloud pour permettre aux développeurs du monde entier d'utiliser une nouvelle pile de bases de données htap en temps réel

Scrape captures 51job Recruitment Information (static page)

Printing diamond of beginner C

用 Keras/TensorFlow 2.9 创建深度学习模型的方法总结

C language to achieve a simple game - minesweeping

C language - Growth Diary -01- count primes and sum
随机推荐
Typescript configuring ts in koa and using koa router
Servlet、ServletConfig、ServletContext
Alchemy experience (model training of deep learning) the necessity of timely adjusting training parameters for some situations (the adjustment of learning rate LR is the primary) summarizes some metho
Pycrypto packaging error
Closure and minimum dependency in database
134. 加油站
Bubble sorting with C language
TypeScript-头文件使用细节
嵌入式软件面试问题总结
Three expressions of integers and their storage in memory
使用 COCO 数据集训练 YOLOv4-CSP 模型
In an activity, view postdelay will cause memory leakage, but will not affect the life cycle execution of the activity.
C language - growth diary-04- preliminary exploration of local variables (local variables)
Typescript type protection
Summary of force deduction questions
Post - payload of interface test
Understanding of Poisson distribution and Poisson process and Erlang distribution and their relations (important theories in queuing theory and operational research)
Dameng database login
C# 微信上传Form-data
用 Keras/TensorFlow 2.9 创建深度学习模型的方法总结