linux多进/线程编程(3)——wait、waitpid函数和孤儿、僵尸进程
当使用fork创建多个进程后,需要解决子进程回收的问题。wait和waitpid函数就是做这个工作的。
假设子进程没有合理的回收,可能会带来两个问题:
1.孤儿进程(父进程挂了,子进程活着),孤儿进程会被init进程回收,可以理解其没有危害,不会占用资源。
2.僵尸进程(子进程挂了,父进程活着),僵尸进程是当父进程活着时,子进程没有其他进程帮忙回收后产生的“有害进程”,所以僵尸必须要回收,否则僵尸进程太多了会占用系统资源。此时就需要用到wait或waitpid函数。
wait和waitpid的区别在于:
wait函数是阻塞的,必须等到子进程被回收才会执行wait之后的代码;
waitpid可以设置为非阻塞的,不过非阻塞可能带来新的问题,子进程还没有回收waitpid这句代码就走完了(一般会写循环,通过判断返回值解决)。
wait:
WAIT(2) Linux Programmer's Manual WAIT(2) NAME
wait, waitpid, waitid - wait for process to change state SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
返回值:
RETURN VALUE
wait(): on success, returns the process ID of the terminated child; on error, -1 is returned. waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state,
then 0 is returned. On error, -1 is returned.
waitpid的参数:
The child state changes to wait for are specified by ORing one or more of the following flags in options:
WEXITED Wait for children that have terminated.
WSTOPPED Wait for children that have been stopped by delivery of a signal.
WCONTINUED Wait for (previously stopped) children that have been resumed by delivery of SIGCONT.
The following flags may additionally be ORed in options:
WNOHANG As for waitpid().
WNOWAIT Leave the child in a waitable state; a later wait call can be used to again retrieve the child status information.
wait用法示例:
pid_t pid = fork();
if (pid == 0) {
//while (true) {
//sleep(1);
//}
printf("i am child, i will die\n");
sleep(2);
//return 101;
exit(2);
} else if (pid > 0) {
printf("i am parent, wait for a child die\n");
int status { 0 };
pid_t wait_pid = wait(&status);//1,阻塞等待(子进程死亡);2,回收子进程资源(避免僵尸进程);3,查看状态(死亡原因)
printf("wait ok, wait_pid=%d, pid=%d\n", wait_pid, pid);
if (WIFEXITED(status)) {
printf("child exit with %d\n", WEXITSTATUS(status));
}
if (WIFSIGNALED(status)) {
printf("child killed by %d\n", WTERMSIG(status));
}
while (true) {
sleep(1);
}
}
waitpid用法示例:
pid_t pid = fork();
int ret { 0 }; if (pid == 0) {
printf("i am child, pid=%d\n", getpid());
sleep(2); exit(101);
} else if (pid > 0) {
printf("i am parent, self=%d, child_pid=%d\n", getpid(), pid); //不阻塞可能会带来一个问题,子进程还没回收,这句代码就走完了,所以要加循环(让代码阻塞在这里。。这。。。那还不如直接用wait????)
//WNOHANG: 不阻塞
int status { 0 }; while ((ret = waitpid(-1, &status, WNOHANG)) == 0) {
sleep(1);
}
printf("ret=%d\n", ret); if (WIFEXITED(status)) {
printf("child exit with %d\n", WEXITSTATUS(status));
} if (WIFSIGNALED(status)) {
printf("child killed by %d\n", WTERMSIG(status));
} ret = waitpid(-1, nullptr, WNOHANG); if (ret < 0) {
perror("wait err");
} while (true) {
sleep(1);
}
}
waitpid回收多个子进程(且忽略子进程状态即死亡原因)
int i { 0 };
int n { 5 };
int ret { 0 };
pid_t pid { 0 };
for (i = 0; i < n; ++i) {
pid = fork();
if (pid == 0) {
printf("i am child, pid=%d\n", getpid());
sleep(2);
break;
}
}
if (pid > 0) {
while ((ret = waitpid(-1, nullptr, WNOHANG)) != -1) {
sleep(1);
printf("ret = %d\n", ret);
}
printf("ret = %d\n", ret);
while (true) {
sleep(1);
printf("i am parent, self=%d, child_pid=%d\n", getpid(), pid);
}
}
linux多进/线程编程(3)——wait、waitpid函数和孤儿、僵尸进程的更多相关文章
- linux多进/线程编程(7)——多线程1(线程的创建,回收,分离,设置线程属性等)
参考资料: 1.博客1:https://blog.csdn.net/zhou1021jian/article/details/71531699 2.博客2:https://blog.csdn.net/ ...
- linux多进/线程编程(4)——进程间通信之pipe和fifo
前言: Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块 ...
- linux多进/线程编程(5)——进程间通信之mmap
参考资料: 1.博客1:https://www.jianshu.com/p/755338d11865 mmap:一种内存映射文件的方法 memory map 父子进程和无亲缘关系的进程,都可以将自身用 ...
- linux多进/线程编程(2)—— fork函数和进程间“共享”数据
参考: 1.博客1:https://www.pianshen.com/article/4305691855/ fork:在原进程的基础上"分叉"出一个子进程,即创建一个子进程. N ...
- linux多进/线程编程(1)—— 基础概念(PCB、MMU、进程状态)
学习大概就是不断迭代.重构的过程,不复习的学习是不负责任的,亦是无用的. 本系列博客主要作为个人记录,主要是贴图和代码,不做详细解释,以后有时间可能会重写:从下一篇开始上代码,代码可以运行是对自己的最 ...
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
linux支持的哪些操作是具有原子特性的?知道这些东西是理解和设计无锁化编程算法的基础. 下面的东西整理自网络.先感谢大家的分享! __sync_fetch_and_add系列的命令,发现这个系列命令 ...
- Linux 网络编程详解六(多进程服务器僵尸进程解决方案)
小结:在点对点p2p程序中,服务器端子程序退出,子进程会主动发送信号,关闭父进程,但是这种模式导致服务器只能支持一个客户端连接,本章节中使用新的框架,子进程退出,不主动发送信号关闭父进程,而是父进程安 ...
- UNIX环境编程学习笔记(21)——进程管理之获取进程终止状态的 wait 和 waitpid 函数
lienhua342014-10-12 当一个进程正常或者异常终止时,内核就向其父进程发送 SIGCHLD信号.父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用的函数(信号处理程序).对于这 ...
- 【Linux】僵尸进程,孤儿进程以及wait函数,waitpid函数(有样例,分析很详细)
本文内容: 1.僵尸进程,孤儿进程的定义,区别,产生原因,处理方法 2.wait函数,waitpid函数的分析,以及比较 背景:由于子进程的结束和父进程的运行是一个异步的过程,即父进程永远无法预测子进 ...
随机推荐
- 用c#实现编写esp32单片机获取DHT11温度传感器参数
欢迎爱好c#的爱好者,本文章我们将用C#的nanoframework框架来编写获取esp32单片机上的DHT11传感器的温度和湿度 实现我们需要准备配置好esp32的环境可以看看之前写的esp32搭建 ...
- 『无为则无心』Python函数 — 40、Python自定义异常
目录 1.使用 raise 语句来抛出异常 (1)抛出异常类 (2)抛出异常类的实例 2.自定义异常类 (1)简单实现 (2)完整实现 在Python中,抛出自定义异常的语法为 raise 异常类对象 ...
- CF1278E Tests for problem D
不难发现为了逐步确定每个点于其相邻点的相交情况,那么我们只可能有两种逐步构造的方式:从根开始往下构造,以及从子树往根上构造.经过很久的尝试,我发现从根往下构造是一件很困难的事情,于是我们可以反过来考虑 ...
- Properties打印流
简介 java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集.它使用键值结构存储数据,每个键及其对应值都是一个字符串.该类也被许多Java类使用,比如获取系统属 ...
- jquery里面的$(this)和this的区别
感谢原文作者:何少旭 原文链接:https://www.cnblogs.com/heshaoxu/p/7672736.html 前言 当你用的是jquery时,就用$(this),如果是JS,就用th ...
- Swift中数据类型
Swift类型的介绍 Swift中的数据类型也有:整型/浮点型/对象类型/结构体类型等等 先了解整型和浮点型 整型 有符号 Int8 : 有符号8位整型 Int16 : 有符号16位整型 Int32 ...
- Linux命令date日期时间和Unix时间戳互转
A.将日期转换为Unix时间戳将当前时间以Unix时间戳表示: date +%s 输出如下: 1361542433 转换指定日期为Unix时间戳: date -d '2013-2-22 22:14' ...
- ANT中的copy和move标签
Copy标签 该标签用于文件或文件集的拷贝,其属性如下: file 表示源文件. tofile 表示目标文件. todir 表示目标目录. overwrite 表示指定是否覆盖目标文件,默认值是不覆盖 ...
- Springboot+Redisson自定义注解一次解决重复提交问题(含源码)
前言 项目中经常会出现重复提交的问题,而接口幂等性也一直以来是做任何项目都要关注的疑难点,网上可以查到非常多的方案,我归纳了几点如下: 1).数据库层面,对责任字段设置唯一索引,这是最直接有效 ...
- 浅谈Java面向对象之抽象类(abstract)
java语言,声明类时格式为: abstract class Db{} 说明Db类为抽象类.抽象方法是说没有方法的实现(方法体)此方法为抽象方法,只有抽象类和接口中才可以有抽象方法.简而言之,含有抽象 ...