Linux内核学习笔记(4)-- wait、waitpid、wait3 和 wait4
进程调用 exit() 退出执行后,被设置为僵死状态,这时父进程可以通过 wait4() 系统调用查询子进程是否终结,之后再进行最后的操作,彻底删除进程所占用的内存资源。 wait4() 系统调用由 linux 内核实现,linux 系统通常提供了 wait()、waitpid()、wait3()、wait4() 这四个函数,四个函数的参数不同,语义也有细微的差别,但是都返回关于终止进程的状态信息。
1、wait() 函数:
wait() 函数的原型是:
#include <sys/types.h> // 提供类型 pid_t 的定义
#include <sys/wait.h> pid_t wait(int *status);
当进程调用 wait() 时,会暂停目前进程的执行(即阻塞),由 wait() 来自动分析是否当前进程的某个子进程已经退出,如果找到了这样一个已经变成僵尸进程的子进程,wait 就会收集这个子进程的信息,并将其彻底销毁后返回;如果没有找到这样一个子进程,wait 就会一直阻塞在这里,直到出现僵尸进程。
参数 status 保存着子进程退出时的一些状态(包括 task_struct、thread_info及内核栈等)它是一个指向 int 类型的指针;如果不在意子进程的结束状态值,只想把这个僵尸进程消灭掉(实际上,大多数时候都是这样做的),则可以将这个参数设为 NULL,即:
pid = wait(NULL); // 不管子进程的结束状态,直接杀死进程
如果 wait() 调用成功,则会返回被收集子进程的进程ID;如果被调用进程没有子进程,则调用失败,返回 -1
接下来用一段代码来演示一下 wait() 的用法:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h> void main(){
pid_t fpid,rpid;
fpid = fork();
if(fpid < ){
perror("error on forking!\n");
}
else if(fpid == ){
printf("this is a child process! the pid is %d\n",getpid());
sleep();
}
else{
rpid = wait(NULL); // 如果 wait()调用成功,则返回子进程的PID;如果调用失败,则返回 -1
printf("Catch the child process with pid of %d\n",rpid);
}
exit();
}
输出结果如下:

关于 status 参数,比较复杂,暂时不做讨论,可以参考这里:https://www.ibm.com/developerworks/cn/linux/kernel/syscall/part3/index.html
2、waitpid() 函数:
函数原型:
#include <sys/types.h>
#include <sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options);
waitpid() 函数的功能与 wait() 的功能类似,不过,它比 wait() 函数多了两个参数:
1)参数 pid 为欲等待的子进程的识别码:
pid < -1 ;等待进程组 ID 为 pid 绝对值的进程组中的任何子进程;
pid = -1 ;等待任何子进程,此时 waitpid() 相当于 wait()。实际上,wait()就是 pid = -1、options = 0 的waitpid(), 且有:
static inline pid_t wait(*status){
return waitpid(-,*status,);
}
pid = 0 ;等待进程组 ID 与当前进程相同的任何子进程(也就是等待同一个进程组中的任何子进程);
pid > 0 ;等待任何子进程 ID 为 pid 的子进程,只要指定的子进程还没有结束,waitpid() 就会一直等下去。
2)参数 options 提供一些额外的选项来控制 waitpid():
WNOHANG;如果没有任何已经结束了的子进程,则马上返回,不等待;
WUNTRACED;如果子进程进入暂停执行的情况,则马上返回,但结束状态不予理会;
也可以将这两个选项组合起来使用,使用 OR 操作。如果不想使用这两个选项,也可以直接把 options 设为0 ,如下:
waitpid(-,NULL,WNOHANG | WUNTRACED); // 没有任何已结束了的子进程或子进程进入暂停执行的状态,则马上返回不等待
waitpid(-,NULL,); // options 设为0,则 waitpid() 会一直等待,直到有进程退出
3)waitpid() 的返回值,有三种:
a)正常返回时,waitpid() 返回收集到的子进程的PID;
b)如果设置了 WNOHANG,而调用 waitpid() 时,没有发现已退出的子进程可收集,则返回0;
c)如果调用出错,则返回 -1,这时erron 会被设置为相应的值以指示错误所在。(当 pid 所指示的子进程不错在,或此进程存在,但不是调用进程的子进程, waitpid() 就会返回出错,这时 erron 被设置为 ECHILD)
1 #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> void main(){
pid_t fpid,rpid; // fpid为fork()的返回值,rpid为waitpid()的返回值
fpid = fork();
if(fpid < ){
printf("error on forking");
}
else if(fpid == ){ // 子进程中 fork() 返回值为0
printf("this is a child process,pid is %d\n",getpid());
sleep(); // 睡眠10s,10s 后子进程退出
exit();
}
do{ // 父进程中,fork()返回新创建子进程的 PID
rpid = waitpid(fpid,NULL,WNOHANG); // 等待 PID = fpid 的进程(即子进程)退出,设置了WNOHANG选项,表明当没有发现已退出的子进程时不用等待直接返回,返回值为0;
if(rpid == ){ // rpid = 0,说明没有发现已退出的子进程
printf("No child exited\n");
sleep();
}
}while(rpid == );
if(fpid == rpid) // 成功收集了退出的子进程,返回值为被收集子进程的PID
printf("successfully get child process %d\n",rpid);
else
printf("error!\n");
}
结果如下:

从结果中可以看到,在子进程休眠的10s时间里,waitpid() 并没有一直等待,而是直接返回0,然后做自己的事情(睡眠1s),如此重复了10次;当子进程退出时,waitpid() 收集到退出的子进程,并返回所收集子进程的PID。
3、wait3()、wait4() 函数:
函数原型:
#include <sys/tpyes.h>
#include <sys/wait.h> pid_t wait3(int *status,int options,struct rusage *rusage);
pid_t wait4(pid_t pid,int *status,int options,struct rusage *rusage);
wait3() 和 wait4() 函数除了可以获得子进程状态信息外,还可以获得子进程的资源使用信息,这些信息是通过参数 rusage 得到的。而 wait3() 与 wait4() 之间的区别是,wait3() 等待所有进程,而 wait4() 可以根据 pid 的值选择要等待的子进程,参数 pid 的意义与 waitpid() 函数的一样。
本文主要参考:
https://www.ibm.com/developerworks/cn/linux/kernel/syscall/part3/index.html
Linux内核学习笔记(4)-- wait、waitpid、wait3 和 wait4的更多相关文章
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记-1.简介和入门
原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
- 20135316王剑桥Linux内核学习笔记
王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...
- 深入理解Linux内核 学习笔记(3)
第三章 进程 可以看到很多熟悉的结构体 进程状态: 可运行状态(TASK_ RUNNING) 进程要么在CPU上执行,要么准备执行. 可巾断的等待状态(TASK_ INTERRUPTIBLE) 进程被 ...
- Linux内核学习笔记之seq_file接口创建可读写proc文件
转自:http://blog.csdn.net/mumufan05/article/details/45803219 学习笔记与个人理解,如有错误,欢迎指正. 温馨提示:建议跟着注释中的编号顺序阅读代 ...
- Linux内核学习笔记
1.vanbreaker的专栏 2.LinuxKernel Exploration 3.DroidPhone的专栏 4.Linux内核研究以及学习文档和ARM学习以及研究的开放文档 [力荐] 5. ...
- 20135316王剑桥Linux内核学习笔记第四周
20135316王剑桥 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC 1000029000 1.内核态:在高执行级别,代码可 ...
- Linux内核学习笔记——内核内存管理方式
一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...
随机推荐
- 关于iPad上模态显示视图中的UITextField,UITextView在输入完成后无法回收键盘的问题解决。
在iPad开发过程中遇到一个问题,UITextField 存在由UIModalPresentationFormSheet 弹出的带导航条的视图控制器中时,调用 resignFirstResponder ...
- ASP.NET Core MVC中Controller的Action如何直接使用Response.Body的Stream流输出数据
在ASP.NET Core MVC中,我们有时候需要在Controller的Action中直接输出数据到Response.Body这个Stream流中,例如如果我们要输出一个很大的文件到客户端浏览器让 ...
- FCC Truncate a string 解决方法
三行搞定 function truncate(str, num) { ab = str.length >num?num>3?str.slice(0,num-3)+ "...&qu ...
- vue 复习(2)v-bind的应用 v-bind:classv-binf:style
dasdclass与style绑定v-bind 1. 绑定HTML Class 对象语法 有些时候我们想动态的切换class的类名.在原生的js或jq中我们就要通过事件来动态的改变class类名,但在 ...
- ztree案例笔记:用户不规范操作导致添加不了节点的问题
我使用ztree开发了简码"万能助手",经过一段时间的观察,发现有个别用户不看教程就开始操作,总能给我折腾出一些让人哭笑不得的问题. 比如,把某个根栏目里的节点全删除,然后发现添加 ...
- php 后端刷新页面
public function index() { $b = date('Y-m-d H:i:s'); header('refresh:10'); $c = strtotime($b); $d = s ...
- PHP实现单文件、多文件上传 封装 面向对象实现文件上传
文件上传配置 客户端配置 1.表单页面 2.表单的发送方式为post 3.添加enctype = "multipart/form-data" <form action=&qu ...
- Hive sql & Spark sql笔记
记录了日常使用时遇到的特殊的查询语句.不断更新- 1. SQL查出内容输出到文件 hive -e "...Hive SQL..." > /tmp/out sparkhive ...
- 文件句柄W模式
f1=open('lo',encoding='utf-8',mode='w')f1.write('w4567')print(f1.tell())f1.close() #tell 告诉指针的位置(按字节 ...
- Oracle入门第二天(上)——基本查询SQL
一.SQL概述 起源于标准不再赘述,主要分为DDL,DML,DCL 相关介绍,参考MySQL章节:http://www.cnblogs.com/jiangbei/p/6696202.html 二.基本 ...