UNIX系统中wait函数族和SIGCHLD信号的关系

2024-01-19 21:38

本文主要是介绍UNIX系统中wait函数族和SIGCHLD信号的关系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

有朋友疑惑“为什么有了wait函数族还需要使用SIGCHLD信号?”。本文详细地阐述UNIX系统中wait函数族和SIGCHLD信号的关系。

一、unix中僵尸进程的含义

关于unix中僵尸进程的含义,APUE2是这样定义:

In UNIX System terminology, a process that has terminated, but whose parent has not yet waited for it, is called a zombie.

也就是说,凡是父进程没有调用wait函数获得子进程终止状态的子进程在终止之后都是僵尸进程,这个概念的关键一点就是父进程是否调用了wait函数。

二、SIGCHLD信号

SIGCHLD信号的含义,APUE2又如是说:

Whenever a process terminates or stops, the SIGCHLD signal is sent to the parent. By default, this signal is ignored, so the parent must catch this signal if it wants to be notified whenever a child's status changes. The normal action in the signal-catching function is to call one of the wait functions to fetch the child's process ID and termination status.

简单的说,子进程退出时父进程会收到一个SIGCHLD信号,默认的处理是忽略这个信号,而常规的做法是在这个信号处理函数中调用wait函数获取子进程的退出状态。

三、既然在SIGCHLD信号的处理函数中要调用wait函数族,为什么有了wait函数族还需要使用SIGCHLD信号?

我们知道,unix中信号是采用异步处理某事的机制,好比说你准备去做某事,去之前跟邻居张三说如果李四来找你的话就通知他一声,这让你可以抽身出来去做这件事,而李四真正来访时会有人通知你,这个就是异步信号一个较为形象的比喻。

一般的,父进程在生成子进程之后会有两种情况:一是父进程继续去做别的事情,类似上面举的例子;另一是父进程啥都不做,一直在wait子进程退出。

SIGCHLD信号就是为这第一种情况准备的,它让父进程去做别的事情,而只要父进程注册了处理该信号的函数,在子进程退出时就会调用该函数,在函数中wait子进程得到终止状态之后再继续做父进程的事情。

最后,我们来明确以下二点:

1)凡父进程不调用wait函数族获得子进程终止状态的子进程在退出时都会变成僵尸进程。

2)SIGCHLD信号可以异步的通知父进程有子进程退出。

 

 

SIGCHLD 和 WAIT 机制的详细解释:

 

1.当子进程结束的时候,父进程会收到SIGCHLD通知
2.进程可以调用wait/waitpid等待此Signal
    a.当所有子进程都在执行的时候,会block
    b.当某个子进程中止,成为zombie的时候,立刻返回
    c.如果没有任何子进程,则返回错误
功能描述: 
等待进程改变其状态。所有下面哪些调用都被用于等待子进程状态的改变,获取状态已改变的子进程信息。状态改变可被认为是:1.子进程已终止。2.信号导致子进程停止执行。3.信号恢复子进程的执行。在子进程终止的情况下,wait调用将允许系统释放与子进程关联的资源。如果不执行wait,终止了的子进程会停留在"zombie"状态。
如果发现子进程改变了状态,这些调用会立即返回。反之,调用会被阻塞直到子进程状态改变,或者由信号处理句柄所中断(假如系统调用没有通过sigaction的SA_RESTART标志重启动)。
wait系统调用挂起当前执行中的进程,直到它的一个子进程终止。waitpid挂起当前进程的执行,直到指定的子进程状态发生变化。默认,waitpid只等待终止状态的子进程,但这种行为可通过选项来改变。waitid系统调用对于等待哪个子进程状态改变提供了更精确的控制。
  
子进程已终止,父进程尚未对其执行wait操作,子进程会转入“僵死”状态。内核为“僵死”状态的进程保留最少的信息量(进程标识,终止状态,资源使用信息),过后父进程执行wait时可以获取子进程信息。只要僵死的进程不通过wait从系统中移去,它将会占据内核进程表中的一个栏位。如果进程表被填满,内核将不能再产生新进程。如果父进程已终止,它的僵死子进程将由init进程收养,并自动执行wait将它们移去。
wait(等待子进程中断或结束)
表头文件
     #include
     #include
定义函数 pid_t wait (int * status);
函数说明 
    wait()会暂时停止目前进程的执行,直到有信号来到或子进程结
    束。如果在调用 wait()时子进程已经结束,则 wait()会立即返
    回子进程结束状态值。子进程的结束状态值会由参数 status 返回,
    而子进程的进程识别码也会一快返回。如果不在意结束状态值,则
    参数 status 可以设成 NULL。       子进程的结束状态值请参考 waitpid( )     
    如果执行成功则返回子进程识别码(PID)             ,如果有错误发生则返回
返回值
     -1。失败原因存于 errno 中。
     waitpid(等待子进程中断或结束)
表头文件
      #include
      #include
定义函数  pid_t waitpid(pid_t pid,int * status,int options);
函数说明
    waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用 wait()时子进程已经结束,则 wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码,
  其他数值意义如下:
    pid0     等待任何子进程识别码为 pid 的子进程。
  参数 option 可以为 0 或下面的 OR 组合:
    WNOHANG 如果没有任何已经结束的子进程则马上返回, 不予以等待。
    WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
  子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:
    WIFEXITED(status)如果子进程正常结束则为非 0 值。
    WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
    WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
    WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
    WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED 时才会有此情况。
    WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
    如果执行成功则返回子进程识别码(PID),如果有错误发生则返回返回值-1。失败原因存于 errno 中。

这篇关于UNIX系统中wait函数族和SIGCHLD信号的关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/623778

相关文章

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用