3、wait和waitpid
1. 函数介绍
wait函数:调用该函数使进程阻塞,直到任意一个子进程结束,或者该进程接收到了一个信号为止,如果该进程没有子进程或该进程的子进程已经结束,wait函数立即返回。
waitpid函数:与wait函数类似,但可以指定子进程的PID以及等待方式(阻塞和非阻塞)。
他们的函数原型如下:
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
函数参数:
status是一个int型的指针,表示程序退出时的状态,如果传入NULL则表示不关心程序退出时的状态。
传入的pid的值有好几种不同的情况:
pid > 0:要等待退出的子进程PID;
pid = -1:等待任意一个子进程退出;
pid = 0:等待其组ID等于调用进程的组ID的任意子进程;
pid < -1:等待其组ID等于pid的绝对值的任意子进程。
options:
WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0。
WUNTRACED:若某实现支持作业控制,则有pid指定的任一子进程状态已暂停,且其状态自暂停以来还没报告过,则返回其状态。(该选项不常用)。
0:同wait,阻塞父进程,等待子进程退出。
其中WNOHANG和WUNTRACED可以通过 “|” 运算符连接。
实际上wait就是封装后的waitpid:
static inline pid_t wait(int * wait_stat)
{
return waitpid(-1, wait_stat, 0);
}
返回值:
正常:结束的子进程的ID号,使用选项WNOHANG而没有子进程结束时返回0,调用出错返回-1。
2. 测试用例
测试代码:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/wait.h>
4
5 int main(int argc, const char *argv[])
6 {
7 int pid;
8 int wait_ret = 0;
9
10 pid = fork();
11
12 if(pid == 0) { /* 子进程 */
13 printf("#############\n");
14 printf("I'm child\n\n");
15 printf("My PID = %d\n", getpid());
16 sleep(2);
17 printf("I'm dead\n");
18 } else if (pid > 0) { /* 父进程 */
19 printf("#############\n");
20 printf("I'm parent\n");
21 printf("wait...\n");
22 wait_ret = wait(NULL);
23 printf("wait_ret = %d\n", wait_ret);
24 }
25
26 return 0;
27 }
测试结果:

从测试结果可以看出,wait函数阻塞了,等子进程结束之后才继续,并且得到的返回值正是子进程的PID。
接下来换waitpid的测试程序:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/wait.h>
4
5 int main(int argc, const char *argv[])
6 {
7 int pid;
8 int wait_ret = 0;
9
10 pid = fork();
11
12 if (pid == 0) { /* 子进程 */
13 printf("#############\n");
14 printf("I'm child\n\n");
15 printf("My PID = %d\n", getpid());
16 sleep(3);
17 printf("I'm dead\n");
18 } else if (pid > 0) { /* 父进程 */
19 printf("#############\n");
20 printf("I'm parent\n");
21 while (1) {
22 wait_ret = waitpid(pid, NULL, WNOHANG);
23 printf("wait_ret = %d\n", wait_ret);
24 sleep(1);
25 if (wait_ret != 0) {
26 printf("Child dead\n");
27 break;
28 }
29 }
30 }
31
32 return 0;
33 }
测试结果:

从结果可以看出,由于传入了WNOHANG,因此waitpid函数不阻塞,在子进程没有退出的时候waitpid返回0,在子进程退出之后waitpid返回的是子进程的PID。
3、wait和waitpid的更多相关文章
- Linux 等待进程结束 wait() 和 waitpid()
若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --> 如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态. -- ...
- linux下使用fork,exec,waitpid模拟system函数
代码如下: #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include &l ...
- 详解wait和waitpid函数
#include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) ...
- 父进程等待子进程结束 waitpid wait
我们一直在强调一个概念就是进程是一个程序执行的实例,是内核在虚拟概念下创建的实体,它实例化的体现在用户态就是程序代码和代码使用的变量(存储空间),在内核态就是内核为我们每个进程所保存的数据结构(状态信 ...
- 系统调用wait、waitpid和exec函数
本文介绍了Linux下的进程的一些概念,并着重讲解了与Linux进程管理相关的重要系统调用wait,waitpid和exec函数族,辅助一些例程说明了它们的特点和使用方法. 1.7 背景 在前面的文章 ...
- linux c学习笔记----进程创建(fork,wait,waitpid)
1.pid_t fork(); (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己 ...
- 对while((pid = waitpid(-1, &stat, WNOHANG)) > 0)不懂的地方,现在懂了
while((pid = waitpid(-1, &stat, WNOHANG)) > 0) 需要写到信号处理函数中,假如有10个子进程 只要父进程能够收到最后一个信号,就能把前面丢失的 ...
- wait、waitpid 僵尸进程 孤儿进程
man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...
- 进程控制之wait和waitpid函数
当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号.因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知.父进程可以选择忽略该信号, ...
- 【转】linux : waitpid函数
原文网址:http://blog.csdn.net/jifengszf/article/details/3067841 [waitpid系统调用] 功能描述: 等待进程改变其状态.所有下面 ...
随机推荐
- sqli-labs 18-19 --Header_injection
sqli-labs 18 知识点 头部注入 报错注入 使用的函数: updatexml (XML_document, XPath_string, new_value); 第一个参数:XML_docum ...
- SpringBoot从入门到精通教程(八)
本主要介绍ElasticSearch 和 SpringBoot 的整合 ,对您有帮助的话,点个关注哦 ElastSearch 介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供 ...
- Flutter ListTile - Flutter每周一组件
该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://github.com/xj124456/fl ...
- Java:利用BigDecimal类巧妙处理Double类型精度丢失
目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数? 如何用BigDecimal解决double精度问题? new BigDecimal(doub ...
- 前端网页打印插件print.js(可导出pdf)
在前端开发中,想打印当前网页的指定区域内容,或将网页导出为多页的PDF,可以借助print.js实现,该插件轻量.简单.手动引入.不依赖其他库.示范项目github:https://github.co ...
- JAVA_JNI字段描述符“([Ljava/lang/String;)V”(Android)
JNI字段描述符"([Ljava/lang/String;)V "([Ljava/lang/String;)V" 它是一种对函数返回值和参数的编码.这种编码叫做JNI字段 ...
- Java源码系列4——HashMap扩容时究竟对链表和红黑树做了什么?
我们知道 HashMap 的底层是由数组,链表,红黑树组成的,在 HashMap 做扩容操作时,除了把数组容量扩大为原来的两倍外,还会对所有元素重新计算 hash 值,因为长度扩大以后,hash值也随 ...
- 表单绑定v-model
表单控件在实际开发中是极为常见的.特别是对于用户信息的提交,需要大量的表单.Vue中使用v-model指令来实现表单元素和数据的双向绑定.此篇记录下其原理,以及当时学习时候的一些小尝试以及修饰符. v ...
- SpringSecurity配置文件
@EnableWebSecurity public class seccurityConfig extends WebSecurityConfigurerAdapter { @Override pro ...
- Linux LVM Logical Volume Management 逻辑卷的管理
博主是一个数据库DBA,但是一般来说,是不做linux服务器LVM 逻辑卷的创建.扩容和减容操作的,基本上有系统管理员操作,一是各司其职,专业的事专业的人做,二是做多了你的责任也多了,哈哈! 但是li ...