24.1 wait 函数说明

24.1.1 waitpid---等待子进程中断或结束

  waitpid(等待子进程中断或结束)
  相关函数 wait,fork

 #include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int * status,int options);
  • 函数说明

    • waitpid() 会暂时停止目前进程的执行,直到有信号来到或子进程结束。
    • 如果在调用 wait() 时子进程已经结束,则 wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。
    • 如果不在意结束状态值,则参数status可以设成NULL。
  • 函数功能:wait 函数的非阻塞版本
  • 函数参数
    • @pid 为欲等待的子进程识别码,其他数值意义如下:

      • pid< -1 等待其组ID等于 pid 的绝对值的任一子进程
      • pid= -1 等待任一子进程,相当于wait()。
      • pid= 0 等待进程组 ID 等于调用进程的组 ID 的任一子进程
      • pid> 0  等待其进程ID 与 pid 相等的子进程。
    • @option可以为0 或下面的OR 组合
      • WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。(若由 pid 指定的子进程没有退出,则立即返回,则 waitpid 不阻塞,此时其返回值为0,若不设置就为阻塞,相当于wait)
      • WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。(若某实现支持作业控制,则由 pid 指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态)
    • @status 子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况
      • WIFEXITED(status)  如果子进程正常结束则为非0值。
      • WEXITSTATUS(status)  取得子进程 exit() 返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
      • WIFSIGNALED(status)  如果子进程是因为信号而结束则此宏值为真(接到一个不能捕捉的信号)
      • WTERMSIG(status)  取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
      • WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED  时才会有此情况。
      • WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED  来判断后才使用此宏。
  • 返回值
    • 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 -1 。失败原因存于 errno 中。

24.1.2 wait --- 等待子进程中断或结束

  wait(等待子进程中断或结束)
  相关函数 waitpid,fork

 #include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int * status);
  • 函数说明

    • wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。
    • 如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。
    • 如果不在意结束状态值,则参数 status 可以设成 NULL。子进程的结束状态值请参考waitpid()。
  • 函数功能:等待子进程退出并回收,防止僵尸进程产生
  • 函数参数
    • @status:为空时,代表任意状态结束的子进程,若不为空,则代表指定状态结束的子进程  
  • 返回值
    • 如果执行成功则返回子进程识别码 (PID),如果有错误发生则返回 -1 。失败原因存于 errno 中。

24.1.3 wait 和 waitpid 函数的区别

  • 在一个子进程终止前,wait 使其调用者阻塞
  • waitpid 由一个选择项,可使调用者不阻塞
  • waitpid 等待一个指定的子进程,而 wait 等待所有的子进程,返回任一终止子进程的状态  

24.2 案例

24.2.1 wait 函数

  process_wait.c

 #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> void out_status(int status)
{
if(WIFEXITED(status)) {
printf("normal exit: %d\n", WEXITSTATUS(status));
} else if(WIFSIGNALED(status)) {
printf("abnormal term: %d\n", WTERMSIG(status));
} else if(WIFSTOPPED(status)) {
printf("stopped sig: %d\n", WSTOPSIG(status));
} else {
printf("unkown sig\n");
}
} int main(void)
{
int status;//存储子进程终止返回的状态
pid_t pid; /* 正常终止 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
exit();//子进程终止运行
} //父进程调用wait函数阻塞,等待子进程结束并回收
wait(&status);
out_status(status);
printf("==========================\n"); /* 非正常终止 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
int i = ;
int j = ;
int k = i / j;
printf("k: %d\n", k);
} wait(&status);
out_status(status);
printf("==========================\n"); /* 暂停 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
pause();//暂停,即为阻塞,等待一个信号将它继续运行
/*
int i = 0;
while(++i > 0) sleep(3);*/
} wait(&status);
out_status(status); return ;
}

  编译运行:

  

  另开一终端,对进程发出停止信号发现无法停止:

  

  这是因为 WIFSTOPPED(status) 和 WSTOPSIG(status) 必须在使用 waitpid 的 option 参数 WUNTRACED  时候才生效,wait 函数无此功能

22.2.2 waitpid

  process_waitpid.c

 #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> void out_status(int status)
{
if(WIFEXITED(status)) {
printf("normal exit: %d\n", WEXITSTATUS(status));
} else if(WIFSIGNALED(status)) {
printf("abnormal term: %d\n", WTERMSIG(status));
} else if(WIFSTOPPED(status)) {
printf("stopped sig: %d\n", WSTOPSIG(status));
} else {
printf("unkown sig\n");
}
} int main(void)
{
int status;//存储子进程终止返回的状态
pid_t pid; /* 正常终止 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
exit();//子进程终止运行
} //父进程调用wait函数阻塞,等待子进程结束并回收
wait(&status);
out_status(status);
printf("==========================\n"); /* 非正常终止 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
int i = ;
int j = ;
int k = i / j;
printf("k: %d\n", k);
} wait(&status);
out_status(status);
printf("==========================\n"); /* 暂停 */
if((pid = fork()) < ) {
perror("fork error");
exit();
} else if(pid == ) {
printf("pid: %d, ppid: %d\n", getpid(), getppid());
pause();//暂停,即为阻塞,等待一个信号将它继续运行
/*
int i = 0;
while(++i > 0) sleep(3);*/
} do{
//子进程若结束,则 pid 为子进程编号
//WNOHANG 非阻塞,waitpid 即子进程还没结束,waitpid 直接返回
pid = waitpid(pid, &status, WNOHANG | WUNTRACED);
if(pid == ) sleep();//pid = 0, 则子进程没有结束,则父进程睡眠 1 s
}while(pid == );
out_status(status); return ;
}

  编译测试与 process_wait.c 一样

  再次发出 kill -19 pid:

  

 

二十四、Linux 进程与信号---wait 函数的更多相关文章

  1. 二十、Linux 进程与信号---非局部跳转

    20.1 setjmp 和 longjmp 函数 20.1.1 函数介绍 #include <setjmp.h> int setjmp(jmp_buf env); 函数功能:设置非局部跳转 ...

  2. 三十、Linux 进程与信号——信号的概念及 signal 函数

    30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...

  3. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  4. 二十六、Linux 进程与信号---system 函数 和进程状态切换

    26.1 system 函数 26.1.1 函数说明 system(执行shell 命令)相关函数 fork,execve,waitpid,popen #include <stdlib.h> ...

  5. 二十五、Linux 进程与信号---exec函数

    25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...

  6. 二十一、Linux 进程与信号---进程查看和进程状态、进程调度和进程状态变化、进程标识

    21.1 进程查看和进程状态 21.1.1 ps 指令 ps 指令通常可以查看到进程的 ID.进程的用户 ID.进程状态和进程的 Command ps:查看当前用户启动的进程 ps -ef:详细查看后 ...

  7. 二十一、Linux 进程与信号---进程资源限制

    21.1 进程资源限制 在操作系统中,我们能够通过函数getrlimit().setrlimit()分别获得.设置每个进程能够创建的各种系统资源的限制使用量. 21.1.1 函数 #include & ...

  8. (二十四)linux新定时器:timefd及相关操作函数

    timerfd是Linux为用户程序提供的一个定时器接口.这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景. 一,相关操作函数 #inclu ...

  9. 二十七、Linux 进程与信号---进程组和组长进程

    27.1 进程组 27.1.1 进程组介绍 进程组为一个或多个进程的集合 进程组可以接受同一终端的各种信号,同一个信号发送进程组等于发送给组中的所有进程 每个进程组有唯一的进程组 ID 进程组的消亡要 ...

随机推荐

  1. Age of Moyu HDU - 6386 (杭电多校7A)

    给出n和点,m条边,每条边有各自的标号,进入第一个标号需要消耗1的费用,此后转换标号需要1费用,在同一个标号上走不需要费用.问你从1到n最少需要多少费用. 最短路变形,把第一个点看成不存在的标号,然后 ...

  2. SpringBoot整合阿里Druid数据源及Spring-Data-Jpa

    SpringBoot整合阿里Druid数据源及Spring-Data-Jpa https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=224 ...

  3. 设置SVN不需要提交的文件

        设置SVN不需要提交的文件 .project .classpath .settings .externalToolBuilders   也可以在TortoiseSVN中设置

  4. HDU/HDOJ 2087 剪花布条

    KMP裸题 (极限5分钟A题) /** freopen("in.in", "r", stdin); freopen("my.out", &q ...

  5. Python函数的定义与调用、返回值、参数

    一.函数是什么 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.比如print(),len()等.但你也可以自己创建函数,这被叫做用户自 ...

  6. JavaScript 正整数正则表达式

    function testNumber(){ var yourinputValue=$("#yourinputId").val();  var reg = /^[1-9]\d*$/ ...

  7. Hibernate3 多对多关系

    学习hibernate的笔迹第三篇,主要内容:多对多关系, 检索策略,HQL查询,QBC,事物管理,c3p0配置 1.1.1  Hibernate的关联关系映射:(多对多) 1.1.1.1     多 ...

  8. 回流(reflow)与重绘(repaint)

    回流(reflow)与重绘(repaint) 很早之前就听说过回流与重绘这两个名词,但是并不理解它们的含义,也没有深究过,今天看了一套网易的题目,涉及到了这两个概念,于是想要把它们俩弄清楚... 一. ...

  9. Httpclient超时timeout设置

    一:连接超时:connectionTimeout 1:指的是连接一个url的连接等待时间. 二:读取数据超时:soTimeout 1:指的是连接上一个url,获取response的返回等待时间. Fo ...

  10. JS(基础)_总结获取页面中元素和节点的方式

    一.前言 1.元素和节点的区别 2.总结获取元素的方式 3.总结获取节点的方式 二.主要内容 1.结点和元素的区别 (1)一些常见基本概念: 文档:document 元素:页面中所有的标签 结点:页面 ...