进程管理之wait和waitpid
僵尸进程
在介绍wait、waitpid和waitid函数之前,首先要介绍一下僵尸进程,因为,这三个函数的本质任务就是处理僵尸进程的问题。
进程会我们的生命体一样,也有消亡。进程在退出时,内核会清理进程几乎所有的资源。例如:内存资源、文件资源、信号量资源、共享内存资源或者引用数减一 又或释放共享内存资源。但还有少量的资源没有被内核清理,例如:进程控制块PCB task_struct、内核栈资源。这些资源没有被释放,是为了保留一些进程退出是的重要信息,例如:进程消耗的系统cpu时间、用户cpu时间;收到了多少信号等待这些信息,类似于“墓志铭”,总结了进程的一生。而wait、waitpid和waitid函数就是来释放这些“墓志铭”信息的。之后进程就脱离了僵尸进程的状态。
进程的僵尸进程的状态,是一种“刀枪不入的状态”,即使是用kill -9 也无法杀死。只能通过wait这些函数活着是通过init进程来“收尸”;
对于创建了很多的子进程的父进程,获取子进程的退出信息是非常有意义的。
wait函数
函数声明
include <sys/wait.h>
pid_t wait(int *status);
返回值
- 返回退出子进程的pid;
- 等待过程中,收到了信号。信号打断了系统调用,并且注册信号处理函数时没有设置SA_RESTAR标识位,系统调用不会被重启。wait函数返回-1,全局变量error=EINIR(表示函数被信号中断);
- 所有需要等待的子进程都已经退出,没有要等的子进程的。wait函数返回-1,全局变量error=ECHLD(表示调用进程时发现并没有子进程需要等待);
由上述返回值的含义,等待所有子进程的退出时,要注意不要丢掉对信号中断情况的考虑,代码如下:
pit_t my_wait(int *state)
{
int retval;
while( (retval=wait(state))!=-1 && (error==EINIR) );
return retval;
}
参数说明
wait函数的参数和waitpid函数的参数是一个意思。但waitpid函数对wait函数的局限性做了扩展,所以,在介绍waitpid时,再来讲wait的参数。
wait函数的局限性
- 不能等待特定的子进程
- 如果子进程不存在,就会阻塞
- 只能探知子进程的死亡,却不能探测子进程的暂停,也无法探知进程的苏醒
waitpid函数
waitpid函数的声明
#include<sys/wait.h>
pid_t waitpid(pit_t pid,int *status,int options);
返回值
返回值和wait函数一样。
参数说明
pid参数
- pid > 0:表示等待进程ID为pid的子进程;
- pid = 0:表示等待与调用进程同一进程组的任意子进程;
- pid = -1:表示等待任意子进程;
- pid < -1:表示等待所有子进程中,进程组ID与pid绝对值相等的所有子进程;
pid参数的理解:
首先给父进程要等待的子进程分类。子进程分为:和父进程同一进程组的子进程,和父进程不同进程组的子进程。子进程可以设置自己的进程组,所以某些子进程不一定和父进程归属于同一个进程组;pid>0,很自然,代表要等待的子进程pid,这叫做“精准打击”;还有情况就是分类等待子进程。由上述分类可知,与父进程为同一进程组的子进程怎么表示,调用waitpid函数的父进程本来就知道自己的进程组pid,所以,不用设置参数pid的值,即给0就行;那与父进程不在同一进程组的子进程的话,就得设置参数pid的值了,但要和“精准打击”的方式区别开,所以给负值,但取绝对值;当然,等待任意子进程的需求还是有的,而现在也正好只剩下一个值“-1”,刚好给它用;综述,通过上面的分析才有了pid参数的使用方式。
内核实现简述
内核之中,wait和waitpid函数调用的都是wait4函数。根据pid的值来给wait_ opts结构体变量wo中的wo_type复制,再以实参的形式传参给do_wait函数,do_wait函数来决定等待什么状态的子进程。
wait4中的部分代码:
struct wait_opts wo;
.
. //给type复制的过程
.
wo.wo_type = type;
wo.wo_pid = pid;
.
.
.
ret = do_wait(&wo);
在do_ wait函数中,主要要完成两个人物,第一,父进程中的每个线程都会去遍历子进程,第二,筛选要等待的子进程;在内核中,task_struct成员中children变量是保存子进程链表的链表头,利用list_for_each_enpty函数来遍历。利用eligible_pid函数来筛选。
遍历子进程代码:
static int do_wait_thread(struct wait_opts *wo,
struct task_struct *tsk)
{
struct task_struct *p;
list_for_each_enpty(p,&tsk->children,silbling)
{
int ret = wait_consider_task(wo,0,p);
if(ret)
return ret;
}
return 0;
}
筛选子进程的代码:
static int eligible_pid(struct wait_opts *wo,
struct task_struct *p)
{
return wo->wo_type == PIDTYPE_MAX ||
task_pid_type(p,wo->wo_type) == wo->wo_pid;
}
当waitpid函数参数pid的值为-1时,wo_type的值为PIDTYPE_MAX;其他三种情况由task_pid_type函数来处理。
参数options
是一个位掩码,可以同时存在多个标志。当options的值为0时,行为和wait类似。
标志位:
- WUNTRACE:关心终止子进程和因信号中断的子进程的信息(阻塞);
- WCONTINUED:关系终止子进程和信号终止后由恢复执行的子进程(阻塞);
- WNOHANG:指定的子进程没有发生变化,waitpid立即返回,返回值为0;出错返回时,返回值为-1,通过error=ECHILD和返回值来区分这两种情况。注意:error的值不会为EINTR,因为信号中断由WUTRACE来控制。
参数status
该参数存储的信息时按位存储的,我们没办法解析status的值,只能通过系统提供的宏去解析。这些宏安功能分可以分为两类:获取子进程状态和判断是非由相应信号产生;
- 进程正常退出
WIFEIXITED(status):正常退出,返回true;
WEXITSTATUS(status):正常退出,获取进程退出状态;
- 进程收到信号退出
WIFSIGNALED(status): 被信号杀死,返回true;
WTREMSIG(status):被信号杀死,返回杀死进程的pid;
WCOREDUMOP(status):子进程产生core dump,返回true;
- 进程收到信号停止
WIFSTOPPED(status):收到相关信号,暂停执行,返回true;
WSTOPSIG(status):如果子进程处于停止状态,该宏返回导致子进
程停止的信号值;
- 进程收到信号回复执行
WIFCONTINUED(status): 递送SIGCONT信号,子进程回复执行,返回true;
没有必要返回使子进程苏醒的信号的值,因为只有唯一一个SIGCONT信号才能使进程又停止状态恢复到执行状态。
进程管理之wait和waitpid的更多相关文章
- 理解Docker容器的进程管理
摘要: Docker在进程管理上有一些特殊之处,如果不注意这些细节中的魔鬼就会带来一些隐患.另外Docker鼓励"一个容器一个进程(one process per container)&qu ...
- Python::OS 模块 -- 进程管理
os模块的简介参看 Python::OS 模块 -- 简介 os模块的文件相关操作参看 Python::OS 模块 -- 文件和目录操作 os模块的进程参数 Python::OS 模块 -- 进程参数 ...
- Linux进程管理知识整理
Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...
- UNIX环境高级编程——进程管理和通信(总结)
进程管理与通信 进程的管理 进程和程序的区别: 进程: 程序的一次执行过程 动态过程,进程的状态属性会发生变化 程序:存放在磁盘上的指令.数据的有序集合 是个文件,可直观看到 程序program ...
- Linux网络技术管理及进程管理(week2_day4)--技术流ken
OSI七层模型和TCP/IP四层模型 OSI七层模型:OSI(Open System Interconnection)开放系统互连参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联 ...
- Linux网络技术管理及进程管理
OSI七层模型和TCP/IP四层模型 OSI七层模型:OSI(Open System Interconnection)开放系统互连参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联 ...
- Liunx网络技术管理及进程管理
Linux网络技术管理及进程管理(week2_day4) OSI七层模型和TCP/IP四层模型 OSI七层模型:OSI(Open System Interconnection)开放系统互连参考模型 ...
- Linux内核分析——第三章 进程管理
第三章 进程管理 3.1 进程 1.进程就是处于执行期的程序:进程就是正在执行的程序代码的实时结果:进程是处于执行期的程序以及相关的资源的总称:进程包括代码段和其他资源. 线程:是在进程中活动的对象. ...
- Linux进程管理 简介
何为进程,我想这个问题大家再熟悉不过了吧,无非就是"执行中的程序"! 概念性的东西本文暂时忽略或者略微一提,详细信息还需要阅读相应的blog或专业书籍.(博主收藏了计算机相关的大量 ...
随机推荐
- 搭建SSM项目框架全过程及思考
1.前言 之前都是在现有框架下进行写代码或者总是看一些别人的架构,总会眼高手低.于是打算自己完整的走一遍流程,同时把所遇到的问题,思考的问题记下来,供大家参考.由于是工作年限不高,属于新手,不足之处还 ...
- 关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)
本文记录一些关于Verilog HDL的一些技巧.易错.易忘点等(主要是语法上),一方面是方便自己忘记语法时进行查阅翻看,另一方面是分享给大家,如果有错的话,希望大家能够评论指出. 关键词: ·技巧篇 ...
- Webi Report 展示 图片链接 (Image Link)
最近由于项目需求,在生成的Webi Report中需要增加一列展示相关数据系统的图片链接,要求用户可以通过点击图片链接展示图片. 方法如下: 1,首先找到系统中图片,查看随机一张图片的属性,找到图片的 ...
- 初次入坑jade模板引擎(一)
最近由于工作需要全栈开发,nodejs做后端,在写一个后台管理系统的时候,我一直在考虑用怎样的方式去写,尝试过依然采用前后端分离的结构.使用json数据进行数据交互的模式,但是尝试过才知道,真的很花时 ...
- JavaScript中的设计模式:单例模式
定义 单例模式就是一个类只能实例化一个对象,并且提供了一个访问它的全局访问点. 一般在实现登陆框,或者一个全局的控制器都会用到单例模式.现实中有window对象,线程池,全局缓存等. 简单实现 var ...
- 通过添加filter过滤器 彻底解决ajax 跨域问题
1.在web.xml添加filter <filter> <filter-name>contextfilter</filter-name> <filter-cl ...
- 华为OJ之放苹果
题目描述: 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法.输入每个用例包含二个整数M和N.0<=m< ...
- dubbo-zookeeper(续)
本篇为继上一篇的续篇,主要内容分为以下几点: 1.zookeeper集群 2.web管理平台 3.dubbo配置说明 接下来我们开始继续吧. 一.zookeeper集群 顾名思义也就是多台zookee ...
- teamviewer试用期到期解决
1.命令行输入:%appdata%删除teamviewer文件夹2.命令行输入:regedit删除teamviewer文件夹3.卸载tv4.控制面板->设备管理器->网络适配器->f ...
- 整理自己的.net工具库
前言 今天我会把自己平日整理的工具库给开放出来,提供给有需要的朋友,如果有朋友平常也在积累欢迎提意见,我会乐意采纳并补充完整.按照惯例在文章结尾给出地址^_^. 之前我开放其他源码的时候(Framew ...