当使用fork创建多个进程后,需要解决子进程回收的问题。waitwaitpid函数就是做这个工作的。

假设子进程没有合理的回收,可能会带来两个问题:

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);
}
}

最新文章

  1. android studio 换护眼的颜色步骤
  2. 如何将ADT项目导入Android studio及常見問題
  3. SevenZip.pas BUG修改版 - 20160613
  4. SSH框架之一详解maven搭建多模块项目
  5. 记 移动端页面中莫名其妙的渲染BUG
  6. sql_查询select
  7. 修改mysql的默认字符集
  8. JavaSE_ 面向对象 总目录(7~10)
  9. 这是您一直期待的所有iOS 11功能的屏幕截图
  10. androidstudio连接SCM Manager上的Git库
  11. IOS学习笔记27—使用GDataXML解析XML文档
  12. Aache的虚拟主机配置虚拟目录
  13. 视频博文结合的教程:用nodejs实现简单的爬虫
  14. 给女朋友讲解什么是Optional【JDK 8特性】
  15. java网络爬虫基础学习(三)
  16. [git]入门-工作区、暂存区、版本库
  17. vue2.0中使用pug(jade)
  18. StringBuilder和+来串接字符串,时间的比较
  19. Django框架(一)
  20. learning ddr mode register MR3

热门文章

  1. linux解析映射文件与自动加载脚本
  2. Kubernetes集群PV和PVC详解
  3. [JavaWeb]Log4j的前因后果
  4. PyTorch 介绍 | AUTOMATIC DIFFERENTIATION WITH TORCH.AUTOGRAD
  5. 根据指定手绘图纸照片行政区划自定义绘制对应区域边界生成geoJOSN的解决方案
  6. JAVA多线程学习五:线程范围内共享变量&amp;ThreadLocal
  7. Cocos2d-JS环境配置教程
  8. memcached 测试代码
  9. Mybatis foreach的用法
  10. PMD的使用学习