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

相关文章

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工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

Windows系统下如何查找JDK的安装路径

《Windows系统下如何查找JDK的安装路径》:本文主要介绍Windows系统下如何查找JDK的安装路径,文中介绍了三种方法,分别是通过命令行检查、使用verbose选项查找jre目录、以及查看... 目录一、确认是否安装了JDK二、查找路径三、另外一种方式如果很久之前安装了JDK,或者在别人的电脑上,想