【IPC 通信】信号处理接口 Signal API(6)

        收发信号思想是 Linux 程序设计特性之一,一个信号可以认为是一种软中断,通过用来向进程通知异步事件。

        本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解信号编程。


wait(2)

遵循 POSIX.1 - 2008

1.库

标准 c 库,libc, -lc

2.接口定义

        这个接口依 _POSIX_C_SOURCE 特性测试宏。

  #include <sys/wait.h>pid_t wait(int *_Nullable wstatus);pid_t waitpid(pid_t pid, int *_Nullable wstatus, int options);int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);/* This is the glibc and POSIX interface; seeNOTES for information on the raw system call. */
        waitid():Since glibc 2.26:_XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809Lglibc 2.25 and earlier:_XOPEN_SOURCE|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L|| /* glibc <= 2.19: */ _BSD_SOURCE

3.接口描述

        所有这些系统调用都是调用进程等待子进程状态变化并获得变化进程相关信息的。这里的状态变化包括:子进程终止、子进程被信号打断、子进程被信号恢复。对于终止的子进程,进程 wait 操作能够让系统释放子进程的相关资源,如果没进行 wait,那么终止的子进程会停留在僵尸状态(参考后面注意章节)。

        如果子进程早已经有状态变化,那么这些调用会立马返回。否则会一直阻塞直到子进程状态变化或者一个信号处理函数打断当前调用(我们假设该信号没有设置 sigaction(2) 的 SA_RESTART标记)。本文中会将子进程状态变化但没有被 wait 的状态称为 waitable。

        wait() 和 waitpid()

        wait() 系统调用会暂停当前调用线程直到任何一个子进程终止。 wait(&wstatus) 的相当于

        waitpid(-1, &wstatus, 0)

        waitpid() 系统调用暂停当前调用线程直到 pid 指定的子进程状态变化。默认情况下,waitpid() 只等待终止的子进程,但是这种行为会受到 options 参数的影响,后面会讲到。

        pid 的值可以是:

        < -1        表示等待所有进程组 ID 是 pid 绝对值的子进程

        -1           表示等待任何子进程

        0            表示等待调用时刻进程组 ID 和调用进程的进程组 ID 相同的任何子进程

        > 0         表示等待进程 ID 为 pid 的子进程

        options 的值为下面值的位或:

        WNOHANG

                如果没有子进程退出,那么就立即返回

        WUNTRACED

                子进程停止时也返回(但是没有被 ptrace(2) 跟踪)。被跟踪的子进程的停止状态在没有指定这个状态时也会返回。

        下面是只适用于 Linux 的一些选项:

        如果 wstatus 不为 NULL,wait() 和 waitpid() 会将状态信息存到它指向的整型数里,这个数能通过以下宏来检查。

        WIFEXITED(wstatus)

        如果子进程正常终止返回 true,即 通过 exit(3)、_exit(2) 或者main() 函数返回。

        WEXISTSTATUS(wstatus)

        返回子进程退出的状态,状态包含的是子进程调用 exit(3)、_exit(2) 或者 main() 返回时参数 status 的低 8 位,只有 WIFEXISTED 返回 true 时才适用。

        WIFSIGNALED(wstatus)

        如果子进程被信号终止返回 true。

        WTERMSIG(wstatus)

        返回导致子进程退出的信号编号,只能在 WIFSIGNALED 返回 true 时适用。

        WCOREDUMP(wstatus)

        如果子进程产生 core dump 返回 true(参考 core(5))。这个宏只有在 WIFSIGNALED 返回 true 时适用。

        这个宏没有在 POSIX.1-2001 中描述,并且在一些 UNIX 实现上也不可用(比如 AIX、SunOS)。因此使用时应该加上 #ifdef WCOREDUMP ... #endif

        WIFSTOPPED(wstatus)

        子进程被信号停止时返回 true,这个只有在 WUNTRACED 调用或者子进程正在被 trace 时适用。

        WSTOPSIG(wstatus)

        返回导致子进程停止的信号,这个宏只能在 WIFSTOPPED 返回 true 时适用。

        WIFCONTINUED(wstatus)

        从 Linux 2.6.10 起,子进程收到 SIGCONT 信号继续执行时返回 true。

waitpid()

        waitpid() 系统调用(Linux 2.6.9 后)提供了对子进程状态变化更加精确的控制。

        idtype 和 id 参数用来选择要等待的子进程,如下:

        idtype == P_PID

                等待进程 ID 号为 id 的子进程

        idtype == P_PIDFD(Linux 5.4 后)

                等待由文件描述符 id 指定的子进程。

        idtype == P_PGID

                等待进程组 ID 为 id 的子进程。Linux 5.4 后,如果 id 为 0,就等待调用时刻和调用进程在统一进程组的所有子进程。

        idtype == P_ALL

                等待任何子进程,忽略 id。

        要等待的状态由 options 指定,是下面标记的位或:

        WEXITED

                等待已经终止的子进程

        WSTOPPED

                等待被信号停止的子进程

        WCONTINUED

                等待被 SIGCONT 信号恢复的子进程(之前被停止过)

        下面这些标记可能也可以用在 options 中:

        WNOHANG

                和 waitpid() 一样

        WNOWAIT

                让子进程继续处于等待状态,后面调用可以继续获取子进程状态信息。

        一旦成功返回,waitpid() 会填充 infop 指向的 siginfo_t 结构:

        si_pid        子进程进程 id

        si_uid        子进程的真实用户 ID(大多数实现没有设置这个字段)

        si_signo        总是 SIGCHLD

        si_status        _exit(2)、exit(3)的返回状态,或者导致子进程终止、停止、继续的信号。si_code 字段可以用来决定如何翻译这个字段。

        si_code        可以设置为:CLD_EXITED(子进程调用了 _exit(2)),CLD_KILLED(子进程被信号杀死),CLD_DUMPED(子进程被信号杀死,并且 core dump),CLD_TRAPPED(trace 子进程停止),以及 CLD_CONTINUED(子进程被 SIGCONT 信号继续)。

        如果在 options 里指定了 WNOHANG,并且没有子进程处于可等待状态,那么 waitpid() 立即返回 0 并且infop 指向的 siginfo_t 结构填充是实现定义的。为了和有一个可等待的子进程的情况区分,在调用和检查这个字段是否为非零前需要将 si_pid 字段清零。

        POSIX.1-2008 技术勘误 1(2013) 中添加了一些要求,当指定 WNOHANG 时并且没有子进程处于可等待状态,那么 waitpid() 应该将清空 si_pid 和 si_signo 字段。在 Linux 以及其服从这个要求的系统实现上,在调用 waitpid() 不用将 si_pid 清零,然而在这一点上,并不是所有实现都遵循 POSIX.1 规范。        

4.返回值

        wait():成功时返回终止的子进程的 ID,失败时返回 -1。

        waitpid():成功时返回状态变化的子进程的 ID,如果指定了 WNOHANG,并且通过 pid 指定了一个或者多个子进程,但是都没有发生状态变化,那么会返回 0。失败时返回  -1。

        waitid():成功或者指定了 WNOHANG 并且通过 id 指定的子进程没有状态变化时返回 0,失败时返回 -1。

        失败时,会更新 errno。

        错误代码如下:

EAGAINPID 文件描述符 id 是非阻塞的并且它指向的进程没有终止
ECHILD调用进程没有任何没等待的子进程(wait())
ECHILD(waitpid() 或者 waitid())pid 指定的进程或者 idtype 和 id 指定的进程不存在,或者不是调用进程的子进程。(这个可能在子进程将 SIGCHILD 信号设置为 SIG_IGN 的情况)
EINTRWNOHANG 没有指定并且捕获了一个非阻塞信号或者 SIGCHILD
EINVALoptions 参数不合法
ESRCHpid 等于 INT_MIN(wait()、waitpid())

5.历史

        wait() 实际上是 libc 实现的库函数,它会调用 wait4(2)。

        在一些架构上,没有 waitpid() 系统调用,这个接口同样是 C 库通过 wait4(2) 系统调用实现的。

        waitid() 系统调用有第五个参数,类型是 struct rusage *,如果这个参数不为空,那么会用它来返回子进程的资源使用信息,这个和 wait4(2) 类似。参考 getrusage(2) 获取更详细信息。

 6.注意

       一个终止了但是没有被 wait 的子进程会称为僵尸进程。内核维护关于僵尸进程的最小信息集合(PID、终止状态、资源使用情况),用来让父进程稍后进行 wait 获取子进程的相关信息。只要僵尸进程没有通过 wait 从系统移除,它就会占用内核进程表的一个位置,如果这个表满了,就无法继续创建进程了。如果父进程终止了,那么它的僵尸子进程就会被 1 号 init 进程接管(或者通过 prctl(2) PR_SET_CHILD_SUBREAPER 指定的最近的 subreaper 领养),1 号进程会自动进程 wait 来移除这些僵尸。

        POSIX.1-2001 指定了如果 SIGCHLD 的处置函数被设置为 SIG_IGN 或者设置了 SIGCHLD 的 SA_NOCLDWAIT 标记,那么子进程终止后不会成为僵尸进程,wait() 或者 waitpid() 调用会阻塞直至所有子进程终止,然后将 errrno 设置为ECHILD 失败。(原来的 POSIX 标准并没有定义这种情况的行为,注意尽管 SIGCHLD 的默认处置函数是 SIG_IGN,明确的 SIG_IGN 设置会僵尸子进程的不同对待行为。)

        Linux 2.6 遵循 POSIX 要求。然而,Linux 2.4 及更早版本并没有:如果 wait() 或者 waitpid() 在 SIGCHLD 被忽略的情况下调用,那么调用行为和 SIGCHLD 没设置是一样的,也就是说调用会一直阻塞直到下一个子进程终止,然后返回对应的进程 ID 和状态信息。

7.BUGS

      根据 POSIX.1-2008,应用调用 waitid() 时,必须保证 infop 指向 siinfo_t 结构(也就是说不能是空指针)。在 Linux 上,如果 infop 为 NULL,waitid() 会成功并且返回等待的进程 ID。应用程序应该避免依赖这个不一致的、非标准的、非必须的特性 。

8.代码

         下面程序演示了 fork(2) 和 waitpid() 的用法。程序创建了一个子进程,如果没有提供命令行参数,那么子进程会使用 pause(2) 来停止,允许用户向其发送信号。否则如果指定了命令行参数,那么子进程立即返回,使用命令行提供的整数作为返回状态值。父进程循环执行,通过 waitpid() 来监视子进程,使用 W*() 宏来分析返回的状态值。

        下面 shell 会话演示了程序的使用:

           $ ./a.out &Child PID is 32360[1] 32359$ kill -STOP 32360stopped by signal 19$ kill -CONT 32360continued$ kill -TERM 32360killed by signal 15[1]+  Done                    ./a.out$

        下面是程序源码: 

       #include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <sys/wait.h>#include <unistd.h>intmain(int argc, char *argv[]){int    wstatus;pid_t  cpid, w;cpid = fork();if (cpid == -1) {perror("fork");exit(EXIT_FAILURE);}if (cpid == 0) {            /* Code executed by child */printf("Child PID is %jd\n", (intmax_t) getpid());if (argc == 1)pause();                    /* Wait for signals */_exit(atoi(argv[1]));} else {                    /* Code executed by parent */do {w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);if (w == -1) {perror("waitpid");exit(EXIT_FAILURE);}if (WIFEXITED(wstatus)) {printf("exited, status=%d\n", WEXITSTATUS(wstatus));} else if (WIFSIGNALED(wstatus)) {printf("killed by signal %d\n", WTERMSIG(wstatus));} else if (WIFSTOPPED(wstatus)) {printf("stopped by signal %d\n", WSTOPSIG(wstatus));} else if (WIFCONTINUED(wstatus)) {printf("continued\n");}} while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));exit(EXIT_SUCCESS);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144448.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

三个要点,掌握Spring Boot单元测试

单元测试是软件开发中不可或缺的重要环节&#xff0c;它用于验证软件中最小可测试单元的准确性。结合运用Spring Boot、JUnit、Mockito和分层架构&#xff0c;开发人员可以更便捷地编写可靠、可测试且高质量的单元测试代码&#xff0c;确保软件的正确性和质量。 一、介绍 本文…

电脑技巧:推荐一款桌面增强工具AquaSnap

目录 一、软件介绍 二、功能介绍 2.1 窗口边缘停靠 2.2、 窗口平铺 2.3、 窗口对齐 2.4 窗口自动拉伸 2.5、同时移动多个窗口 2.6 、支持窗口置顶 2.7、 鼠标快捷方式 2.8、 键盘快捷键 三、软件特色 四、软件获取 一、软件介绍 AquaSnap(界面增强软件)是一款功能…

面试总结之Spring篇

一、AOP 1、什么是AOP 1.1、概述 AOP&#xff08;Aspect-Oriented Programming&#xff09;&#xff1a;面向切面编程&#xff0c;即把一些业务逻辑中的相同代码抽取出来&#xff0c;让业务逻辑更加简练清爽 如果要CRUD写一堆业务&#xff0c;可如何实现业务代码前后进行打印…

01-http概述

HTTP概述 HTTP使用的是可靠地数据传输协议。HTTP属于应用层协议 Web客户端和服务器 web服务器&#xff1a;又称http服务器&#xff0c;用于存储web内容&#xff0c;并向web客户端提供web内容web客户端&#xff1a;用于请求web服务器的应用软件&#xff0c;常见为浏览器 资源…

关于表单快速开发低代码技术平台的内容介绍

运用什么样的表单快速开发软件平台可以实现高效率创收&#xff1f;随着科技的进步和飞速发展&#xff0c;专业的低代码技术平台已经走入了很多企业的办公职场中&#xff0c;它们灵活、轻量级、优质、高效、易维护等优势特点&#xff0c;可以高效助力广大企业提质增效&#xff0…

多线程 dispatch

51423 https://blog.csdn.net/yanhaijunyan/article/details/115083522

快速将iPhone大量照片快速传输到电脑的办法!

很多使用iPhone 的朋友要将照片传到电脑时&#xff0c;第一时间都只想到用iTunes 或iCloud&#xff0c;但这2个工具真的都非常难用&#xff0c;今天小编分享牛学长苹果数据管理工具的照片传输功能&#xff0c;他可以快速的将iPhone照片传输到电脑上&#xff0c;并且支持最新的i…

用友移动管理系统任意文件上传漏洞

一、漏洞描述 用友移动管理系统 uploadApk.do 文件存在任意文件上传 二、fofa查询 body"../js/jslib/jquery.blockUI.js" 三、漏洞利用 poc POST /maportal/appmanager/uploadApk.dopk_obj HTTP/1.1 Host: ip:port Cache-Control: max-age0 Upgrade-Insecure-Req…

web前端tips:js继承——寄生式继承

上篇文章给大家分享了 js继承中的 原型式继承 web前端tips&#xff1a;js继承——原型式继承 今天给大家分享一下 js 继承中的 寄生式继承 寄生式继承 寄生式继承&#xff08;Parasitic Inheritance&#xff09;是一种基于原型式的继承方式&#xff0c;它通过创建一个仅用于…

【AI视野·今日NLP 自然语言处理论文速览 第四十三期】Thu, 28 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 28 Sep 2023 Totally 38 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Cross-Modal Multi-Tasking for Speech-to-Text Translation via Hard Parameter Sharing Authors Brian Yan,…

nodejs+vue电影网站elementui

第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;技术背景 5 3.2.2经济可行性 6 3.2.3操作可行性&#xff1a; 6 3.3 项目设计目标与原则 6 3.4系统流程分析 7 3.4.1操作流程 7 3.4.2添加信息流程 8 3.4.3删除信息流程 9 第4章 系统设计 11 …

AI类APP能做什么

AI类APP可以实现多种功能&#xff0c;涵盖了各种领域和用途。以下是一些常见的AI类APP示例以及它们主要实现的功能&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.语音助手&#xff08;Voice Assis…

【项目】基于C++11实现的数据库连接池

文章目录 前置知识关键技术点项目背景连接池功能点介绍MySQL Server参数介绍功能设计连接池功能点介绍开发平台选型 关于MySQL数据库编程MySQL接口介绍 测试表设计Connection设计数据库配置文件mysql.conf日志文件log.hppConnectionPool设计压力测试源码链接&#xff1a; 前置知…

05-前端基础CSS第三天

01-CSS三大特性之层叠性 1.CSS的三大特性 CSS有三个非常重要的三个特性&#xff1a;层叠性、继承性、优先级。 1.1 层叠性 相同选择器给设置相同的样式&#xff0c;此时一个样式就会**覆盖&#xff08;层叠&#xff09;**另一个冲突的样式。层叠性主要解决样式冲突的问题。…

视频增强修复工具Topaz Video AI mac中文版安装教程

Topaz Video AI mac是一款使用人工智能技术对视频进行增强和修复的软件。它可以自动降噪、去除锐化、减少压缩失真、提高清晰度等等。Topaz Video AI可以处理各种类型的视频&#xff0c;包括低分辨率视频、老旧影片、手机录制的视频等等。 使用Topaz Video AI非常简单&#xff…

LaTex一行排列多个图,并且加入每个图都添加小标题

1、Latex中将字母上下方插入字母数字\mathop{a}\limits_{i1}&#xff1a; a i 1 \mathop{a}\limits_{i1} i1a​ 2Latex罗马数字 大写&#xff1a;\uppercase\expandafter{\romannumeral20} 小写&#xff1a;\romannumeral20 2、LaTex一行排列多个图&#xff0c;并且加入每个…

Vue中自定义实现类似el-table的表格效果实现行颜色根据数据去变化展示

主要使用div布局实现表格效果&#xff0c;并使用渐变实现行背景渐变的效果 页面布局 <div class"table-wrap"><div class"table-title"><divv-for"(item, index) in tableColumn":key"index":prop"item.prop&qu…

React Native从0到1开发一款App

先贴上项目地址&#xff0c;有需要的大佬可以去github看看&#xff1a; WinWang/RNOpenEye: React Native(0.72)版本开眼OpenEye项目 (github.com) React Native&#xff08;0.72&#xff09;版本OpenEye项目&#xff0c;主要用来熟悉并上手RN项目的开发&#xff0c;是Flutte…

嵌入式Linux应用开发-第七章-RK3288和 RK3399的 LED驱动程序

嵌入式Linux应用开发-第七章-RK3288和 RK3399的 LED驱动程序 RK3288和 RK3399的 LED驱动程序7.3 RK3288和 RK3399的 LED驱动程序7.3.1 原理图7.3.1.1 fireflye RK3288的 LED原理图7.3.1.2 firefly RK3399的 LED原理图 7.3.2 所涉及的寄存器操作7.3.2.1 RK3288的 GPIO8_A1引脚7.…

Docker 容器技术 (上) 环境安装和部署、容器镜像、使用IDEA构建Springboot程序镜像、远程仓库、容器网络管理

Docker容器技术 文章目录 Docker容器技术容器技术入门环境安装和部署从虚拟机到容器容器工作机制简述 容器与镜像初识容器镜像镜像结构介绍构建镜像发布镜像到远程仓库实战&#xff1a;使用IDEA构建SpringBoot程序镜像 容器网络管理容器网络类型用户自定义网络容器间网络容器外…