2.5 进程控制之wait函数
一、绪论
一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果
是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或waitpi
d获取这些信息,然后彻底清除掉这个进程。
二、wait()
1. 功能:父进程调用wait函数可以回收子进程终止信息。该函数有三个功能:
① 阻塞等待子进程退出
② 回收子进程残留资源
③ 获取子进程结束状态(退出原因)。
wait一旦被调用,就会一直阻塞在这里,直到有一个子进程退出出现为止。
2. 函数原型:
pid_t wait(int *status); 成功:清理掉的子进程ID;失败:-1 (没有子进程)
使用wait函数传出参数status来保存进程的退出状态 (正常终止→退出值;异常终止→终止信号)。借助宏函数来进一步判断进程终止的具体原因。
宏函数可分为如下三组:
1). WIFEXITED(status) 为非0 → 进程正常结束
WEXITSTATUS(status) 如上宏为真,使用此宏 → 获取进程退出状态 (exit的参数)
2). WIFSIGNALED(status) 为非0 → 进程异常终止
WTERMSIG(status) 如上宏为真,使用此宏 → 取得使进程终止的那个信号的编号。
*3). WIFSTOPPED(status) 为非0 → 进程处于暂停状态
WSTOPSIG(status) 如上宏为真,使用此宏 → 取得使进程暂停的那个信号的编号。
WIFCONTINUED(status) 为真 → 进程暂停后已经继续运行
3. 例程
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h> int main(void)
{
pid_t pid, wpid;
int status; //定义传出参数 pid = fork();
if(pid == -){
perror("fork error");
exit();
} else if(pid == ){ //子进程
printf("I'm process child, pid = %d\n", getpid());
#if 0
execl("./abnor", "abnor", NULL);
perror("execl error");
exit();
#endif
sleep();
exit();
} else {
//wpid = wait(NULL); //无传出参数,无需判断
wpid = wait(&status); //status为传出参数,wpid返回的进程ID
if(WIFEXITED(status)){ //正常退出 非0
printf("I'm parent, The child process%d exit normally\n", wpid);
printf("return value:%d\n", WEXITSTATUS(status));//获取退出值
} else if (WIFSIGNALED(status)) { //异常退出
printf("The child process exit abnormally, killed by signal %d\n", WTERMSIG(status));//获取终止信号编号
} else {
printf("other...\n");
}
}
return ;
}
编译与执行结果:

异常退出:

二、waitpid()
1. 功能与wait相同,但可指定pid进程清理,可以不阻塞。
pid_t waitpid(pid_t pid, int *status, in options); 成功:返回清理掉的子进程ID;失败:-(无子进程)
特殊参数和返回情况,参数pid:
> 0 回收指定ID的子进程
-1 回收任意子进程(相当于wait)
0 回收和当前调用waitpid一个组的所有子进程
< -1 回收指定进程组内的任意子进程
注意:
1)参3为WNOHANG(非阻塞),且子进程正在运行,则返回0。
2)一次wait或waitpid调用只能清理一个子进程,清理多个子进程应使用循环。
2. 例程一
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
int i;
int stat_val; pid = fork(); if (pid < ) {
perror("fork failed");
exit();
}
if (pid == ) {
for (i = ; i > ; i--) {
printf("This is the child\n");
sleep();
}
exit();
} else {
waitpid(pid, &stat_val, ); //0阻塞
if (WIFEXITED(stat_val)) ////stat_val为传出参数
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
else if (WIFSIGNALED(stat_val))
printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
}
return ;
}
编译与执行结果:

例程二(循环清理多个子进程)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> int main(int argc, char *argv[])
{
int n = , i;
pid_t p; for(i = ; i < n; i++) {
p = fork();
if(p == ) break;
}
if(n == i){ // parent
sleep(n);
printf("I am parent, pid = %d\n", getpid());
for (i = ; i < n; i++) {
p = waitpid(, NULL, WNOHANG);
printf("wait pid = %d\n", p);
}
} else {
sleep(i);
printf("I'm %dth child, pid = %d\n", i+, getpid());
}
return ;
}
编译与执行结果:

2.5 进程控制之wait函数的更多相关文章
- 进程控制之fork函数
一个现有进程可以调用fork函数创建一个新进程. #include <unistd.h> pid_t fork( void ); 返回值:子进程中返回0,父进程中返回子进程ID,出错返回- ...
- 进程控制之exec函数
用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序.当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行.因为调用exec并不创 ...
- Linux系统编程_8_进程控制之fork_wait_waitpid函数
fork函数: #include <unistd.h> pid_t fork(void); fork用来创建一个子进程: 特点: fork调用后会返回两次,子进程返回0,父进 ...
- linux c编程:进程控制(三)_exec函数
fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...
- 进程控制之exit函数
进程有下面5种正常终止方式: (1)在main函数内执行return语句.这等效于调用exit. (2)调用exit函数.此函数有ISO C定义,其操作包括调用各终止处理程序(终止处理程序在调用ate ...
- 进程控制之system函数
ISO C定义了system函数,但是其操作对系统的依赖性很强.POSIX.1包括了system接口,它扩展了ISO C定义,以描述system在POSIX.1环境中的运行行为. #include & ...
- 进程控制之waitid函数
Single UNIX Specification的XSI扩展包括了另一个取进程终止状态的函数--waitid,此函数类似于waitpid,但提供了更多的灵活性. #include <sys/w ...
- 进程控制之vfork函数
vfork函数的调用序列和返回值与fork相同,但两者的语义不同. vfork用于创建一个新进程,而新进程的目的是exec一个新程序.vfork和fork一样都创建一个子进程,但是它并不将父进程的地址 ...
- linux的fork()函数-进程控制
进程作为构成系统的基本细胞,不仅是系统中独立活动的实体,而且是独立竞争资源的基本实体.它要经历创建.执行.等待.终止等一系列过程. 一.fork入门知识(转载) 一个进程,包括代码.数据和分配给进程的 ...
随机推荐
- 开发者为何对Service Fabric爱不释手?值得关注!
有了它,人人都可开发高可用高伸缩应用.今天小编就为大家介绍一款开发者的“利器”——Service Fabric . 在介绍它之前,先来了解一下它的背景. Service Fabric 是一款应用程序平 ...
- windows下使用VNC进行远程连接
在 windows 电脑上安装 VNC,包含 VNC server 和 VNC viewer,如果仅需要被操控或操控他人,选择型下载安装 VNC server 或 VNC viewer 即可. 在需要 ...
- Lucene.net入门学习(结合盘古分词)(转载)
作者:释迦苦僧 出处:http://www.cnblogs.com/woxpp/p/3972233.html 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显 ...
- FastDFS 初始
FastDFS 详细介绍 FastDFS是一个开源的分布式文件系统,她对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为 ...
- March 21 2017 Week 12 Tuesday
Sometimes ever, sometimes never. 相聚有时,后会无期. Maybe love is something we can't touch but we can feel w ...
- 一点一点学写Makefile(3)-增加第三方库和头文件
我们在写代码的时候不一定都是有自己来完成,一个工程中会大量使用一些比较优秀的动态库.静态库等,我们在使用这些库完成所有的代码后,需要在编译的时候将这些库使用的头文件添加到我们的工程上,将他的库文件也添 ...
- MovieReview—The Foreigner (英伦对决)
The Foreigner's theme is revenge.The whole story is carried out in two dimensions:political struggle ...
- Velocity 模板
Velocity 模板引擎介绍 引:https://www.ibm.com/developerworks/cn/java/j-lo-velocity1/ 在 现今的软件开发过程中,软件开发人员将更多的 ...
- POJ 1830 开关问题 【01矩阵 高斯消元】
任意门:http://poj.org/problem?id=1830 开关问题 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 1 ...
- application配置和profile隔离配置
前言 github: https://github.com/vergilyn/SpringBootDemo 说明:我代码的结构是用profile来区分/激活要加载的配置,从而在一个project中写各 ...