本文内容:

1.僵尸进程,孤儿进程的定义,区别,产生原因,处理方法

2.wait函数,waitpid函数的分析,以及比较

背景:由于子进程的结束和父进程的运行是一个异步的过程,即父进程永远无法预测子进程什么时候结,所以就产生了孤儿进程和僵尸进程

定义:

孤儿进程:即父进程退出后,它的一个或多个子进程还在运行,那么这些子进程叫做孤儿进程

僵尸进程:如果子进程退出,但是父进程没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符pid仍然保存在系统中,那么该子进程叫做僵尸进程

区别:

孤儿进程是父进程已退出,而子进程没有退出,僵尸进程是父进程没有退出,而子进程退出了

处理方法:

1.孤儿进程将会被1号进程init进程收养,并且由init进程完成对他们的状态收集工作

2.当一个进程终止后,它的父进程需要调用wait函数(阻塞等待)或waitpid函数(非阻塞等待)获得子进程的终止状态!【父进程通过进程等待的方式,回收子进程的资源,获取子进程退出信息】

僵尸进程样例:

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
using namespace std; int main()
{
pid_t pid=fork(); if(pid>0)
{
cout<<"in paraten process,sleep..."<<endl;
sleep(3);
cout<<"after sleep"<<endl;
}
else if(pid==0)
{
cout<<"in child process"<<endl;
exit(0);
}
return 0;
}

分析:父进程睡眠3s等待子进程结束,父进程没有调用函数等待子进程回城子进程的资源,所以子进程变成了一个僵尸进程

当这个父进程醒来然后也退出之后,该子进程就变成孤儿进程然后被1号init进程收养了,而init进程会周期性的调用wait函数来清除各个僵尸子进程

wait函数的原理:进程调用wait,然后阻塞自己,然后寻找僵尸子进程,找到了则销毁子进程然后返回,没有找到则一直阻塞直到找打僵尸子进程为止

样例程序:使用wait函数来回收僵尸进程

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std; int main()
{
pid_t pid=fork(); if(pid>0)
{
cout<<"in parate process"<<endl;
pid_t pr=wait(NULL);
cout<<"in parent process,I catched a child process with pid of "<<pid<<endl;
}
else if(pid==0)
{
cout<<"in child process,PID="<<getpid()<<" PPID:"<<getppid()<<endl;
exit(0);
}
return 0;
}

wait函数原型:

pid_t wait(int *status)

如果status的值不是NULL,wait就会把子进程退出时的状态码取出存入status中,这样我们可以知道子进程是正常退出还是非正常退出

需要注意的是,子进程状态信息被放在一个整数的不同二进制位中,所以有一个专门的宏macro来读取信息,比如WIFEXITED(status),子进程正常退出返回非0值,当子进程是正常退出时,我们可以使用WEXITSTATUS来获取子进程的返回值,比如子进程返回5,那么我们就可以获取这个返回值

样例程序:利用宏获得子进程的返回值:

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std; int main()
{
pid_t pid=fork(); if(pid<0)
{
cout<<"fork error"<<endl;
return 0;
}
else if(pid>0)
{
cout<<"in parate process"<<endl; int status=-1;
pid_t pr=wait(&status); if(WIFEXITED(status))
{
cout<<"the child process exit normal"<<endl;
cout<<"the child return code is "<<WEXITSTATUS(status)<<endl;
}
else
{
cout<<"the child process exit abnormal,pid="<<pr<<endl;
}
}
else if(pid==0)
{
cout<<"in child process,PID="<<getpid()<<" PPID:"<<getppid()<<endl;
exit(6);
}
return 0;
}

分析:子进程返回6,父进程通过宏获得了子进程的返回值,需要注意的是:返回值有一定的大小,太大了不可以,因为整个整数的比特位存储的是子进程返回的一些信息,有位数限制

waitpid函数原型:

pid waitpid(pid_t pid,int *status,int options)

pid参数:

1)pid>0:只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去

2)pid=-1:等待任何一个子进程,没有限制,此时和wait函数作用一模一样

3)pid<-1:等待一个指定进程组中的任何子进程,进程组号=pid的绝对值

4)pid=0:等待一个指定进程组中的任何子进程,进程组号为pid的值

options参数:

1)options=WNOHANG,即使子进程没有退出,它也会立即返回,不会像wait那样永远等下去

2)options=WUNTRECED,子进程睡眠则马上返回,但结束状态不予理会

3)options=0,不使用该参数

和wait函数相比,waitpid其实是wait函数的封装,waitpid可以指定等待的子进程,并且指定返回的条件!

样例程序:使用waitpid收集子进程的信息

#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std; int main()
{
pid_t pid=fork();
pid_t pr; if(pid<0)
{
cout<<"fork error"<<endl;
return 0;
}
else if(pid>0)
{
cout<<"in parate process"<<endl;
do
{
pr=waitpid(pid,NULL,WNOHANG);
if(pr==0)
{
cout<<"no child exit"<<endl;
sleep(1);
}
}
while(pr==0);
if(pr==pid)
{
cout<<"successfuly get child "<<pid<<endl;
}
else
{
cout<<"some error cvcured"<<endl;
}
}
else if(pid==0)
{
cout<<"in child process,PID="<<getpid()<<" PPID:"<<getppid()<<endl;
sleep(10);
exit(11);
}
return 0;
}

分析:waitpid采用了WNOHANG参数,所以waitpid不会停留在那里等待,也就是说父进程不会阻塞在那里等待子进程返回,它会立即返回然后去做自己的事情,所以需要加个循环直到等待到进程为止,相当于轮询

总结:waitpid函数是wait函数的封装,作用一样,但是比wait函数更加灵活了,可以指定需要等待的子进程,可以设置等待的规则!

【Linux】僵尸进程,孤儿进程以及wait函数,waitpid函数(有样例,分析很详细)的更多相关文章

  1. 进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程

    1.进程 什么是进程: 一个正在被运行的程序就称之为进程,是程序具体执行的过程,是一种抽象概念,进程来自操作系统 2.多进程  多个正在运行的程序 在python中实现多线程的方法 from mult ...

  2. day34 并行并发、进程开启、僵尸及孤儿进程

    day34 并行并发.进程开启.僵尸及孤儿进程 1.并行与并发 什么是并行? 并行指的是多个进程同时被执行,是真正意义上的同时 什么是并发? 并发指的是多个程序看上去被同时执行,这是因为cpu在多个程 ...

  3. 僵尸进程 & 孤儿进程

    参考博文 基本概念 僵尸进程:是所有进程都会进入的一种进程状态,子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的 PID 和 进程描述符 等资源 ...

  4. Go Exec 僵尸与孤儿进程

    原文地址:Go Exec 僵尸与孤儿进程 最近,使用 golang 去管理本地应用的生命周期,期间有几个有趣的点,今天就一起看下. 场景一 我们来看看下面两个脚本会产生什么问题: 创建两个 shell ...

  5. Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信

    Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...

  6. linux下的进程(孤儿进程、僵尸进程)

    linux提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息,就可以得到.这种机制就是:在每个进程退出的时候,内核释放该进程所有的资源,包括打开文件,占用的内存等.但是仍然为其保留一定的信息 ...

  7. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

  8. 浅析僵尸进程&孤儿进程

    0x01 前言 此文出自:https://www.cnblogs.com/Anker/p/3271773.html 博文主要用unix/linux举例,但道理没问题的同样有助于在Python中理解僵尸 ...

  9. day 7-3 僵尸进程,孤儿进程与守护进程

    一.基本定义 正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程完成它的工作终止之后,它 ...

随机推荐

  1. 11-Flutter移动电商实战-首页_屏幕适配方案和制作

    1.flutter_ScreenUtil插件简介 flutter_ScreenUtil屏幕适配方案,让你的UI在不同尺寸的屏幕上都能显示合理的布局. 插件会让你先设置一个UI稿的尺寸,他会根据这个尺寸 ...

  2. robot framework的使用方法

    1.后台代码: 目录结构: 测试代码:Arithmetic.py 2.开始编写用例 直接在eclipse上新建一个txt文件即可,或者是通过ride编写用例. (1).首先在eclipse上新建目录T ...

  3. Web API design

    Web API design 28 minutes to read Most modern web applications expose APIs that clients can use to i ...

  4. CSS行内块元素(内联元素)

    一.典型代表 input img 二.特点: 在一行上显示 可以设置宽高 <style type="text/css"> img{ width: 300px; /* 顶 ...

  5. 计蒜之道 百度AI小课堂-上升子序列

    计蒜之道 百度AI小课堂-上升子序列 题目描述 给一个长度为 \(n\) 的数组 \(a\) .试将其划分为两个严格上升子序列,并使其长度差最小. 输入格式 输入包含多组数据. 数据的第一行为一个正整 ...

  6. hive集成kerberos

    1.票据的生成 kdc服务器操作,生成用于hive身份验证的principal 1.1.创建principal # kadmin.local -q “addprinc -randkey hive/yj ...

  7. Jmeter(四十三)_性能测试分配堆内存

    内存泄漏.内存溢出是什么? 内存泄露是指你的应用使用资源之后没有及时释放,导致应用内存中持有了不需要的资源,这是一种状态描述: 内存溢出是指你应用的内存已经不能满足正常使用了,堆栈已经达到系统设置的最 ...

  8. python使用ldap3进行接口调用

    把自己使用到的ldap调用的代码分享出来,希望大家可以参考 #!/usr/bin/python # -*- coding: utf-8 -*- """ @Time : 2 ...

  9. 《Hadoop综合大作业》

    作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3339 我主要的爬取内容是关于热门微博文章“996”与日剧<我要 ...

  10. WEB API 的设计与开发