【linux学习指南】SIGCHLD信号

请添加图片描述

文章目录

  • 📝SIGCHLD信号
  • 🚩总结


📝SIGCHLD信号

进程⼀章讲过⽤waitwaitpid函数清理僵⼫进程,⽗进程可以阻塞等待⼦进程结束,也可以⾮阻塞地查询是否有⼦进程结束等待清理(也就是轮询的⽅式)。采⽤第⼀种⽅式,⽗进程阻塞了就不能处理⾃⼰的⼯作了;采⽤第⼆种⽅式,⽗进程在处理⾃⼰的⼯作的同时还要记得时不时地轮询⼀下,程序实现复杂。

其实,⼦进程在终⽌时会给⽗进程发SIGCHLD信号,该信号的默认处理动作是忽略,⽗进程可以⾃定义SIGCHLD信号的处理函数,这样⽗进程只需专⼼处理⾃⼰的⼯作,不必关⼼⼦进程了,⼦进程终⽌时会通知⽗进程,⽗进程在信号处理函数中调⽤wait清理⼦进程即可。

请编写⼀个程序完成以下功能:⽗进程fork出⼦进程,⼦进程调⽤exit(2)终⽌,⽗进程⾃定义SIGCHLD信号的处理函数,在其中调⽤wait获得⼦进程的退出状态并打印。

事实上,由于UNIX的历史原因,要想不产⽣僵⼫进程还有另外⼀种办法:⽗进程调⽤sigactionSIGCHLD的处理动作置为SIG_IGN,这样fork出来的⼦进程在终⽌时会⾃动清理掉,不会产⽣僵⼫进程,

也不会通知⽗进程。系统默认的忽略动作和⽤⼾⽤sigaction函数⾃定义的忽略通常是没有区别的,但这是⼀个特例。此⽅法对于Linux可⽤,但不保证在其它UNIX系统上都可⽤。请编写程序验证这样做不会产⽣僵⼫进程。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

void handler(int sig)
{
    pid_t id;
    while ((id = waitpid(-1, NULL, WNOHANG)) > 0)
    {
        printf("wait child success: %d\n", id);
    }
    printf("child is quit! %d\n", getpid());
}

int main()
{
    signal(SIGCHLD, handler);
    pid_t cid;
    if ((cid = fork()) == 0)
    { // child
        printf("child : %d\n", getpid());
        sleep(3);
        exit(1);
    }
    while (1)
    {
        printf("father proc is doing some thing!\n");
        sleep(1);
    }
    return 0;
}

在这里插入图片描述

查看进程代码

while true; do   
    ps -ajx | grep sig  
    ps -ajx | head -1  
    sleep 1  
done

在这里插入图片描述

  1. 信号处理函数 handler
void handler(int sig)
{
    pid_t id;
    while ((id = waitpid(-1, NULL, WNOHANG)) > 0)
    {
        printf("wait child success: %d\n", id);
    }
    printf("child is quit! %d\n", getpid());
}
  • 这是一个自定义的信号处理函数,用于处理特定的信号(在程序中注册它来处理 SIGCHLD 信号)。当接收到相应信号时,这个函数就会被调用执行。
  • 函数接收一个整型参数 sig,代表接收到的信号编号,不过在这个函数内部其实并没有使用这个参数来做不同的分支处理,它主要关注的是处理子进程退出的情况。
  • 在函数内部有一个 while 循环,循环条件是 (id = waitpid(-1, NULL, WNOHANG)) > 0
    • waitpid 函数用于等待子进程状态改变并获取相关信息,这里的参数 -1 表示等待任意子进程(如果指定具体的子进程ID,就只会等待那个特定的子进程);NULL 作为第二个参数表示不关心子进程的终止状态信息(如果想获取具体状态,可以传入相应的指针来接收状态值);WNOHANG 是一个宏,它使得 waitpid 函数在没有已终止的子进程可等待时立即返回,而不是阻塞等待。
    • 只要 waitpid 调用返回的值大于 0,就意味着成功等到了一个已终止的子进程,此时进入循环体,通过 printf 打印出等待到的子进程的进程ID(printf("wait child success: %d\n", id);)。这个循环可以连续处理多个同时终止的子进程(如果存在这种情况)。
  • 循环结束后(也就是没有已终止的子进程可等待了),通过 printf 打印出当前进程(也就是父进程)的进程ID,表示子进程已经退出完毕,当前提示信息所在的进程(父进程)还在运行(printf("child is quit! %d\n", getpid());)。
  1. main 函数部分
int main()
{
    signal(SIGCHLD, handler);
    pid_t cid;
    if ((cid = fork()) == 0)
    { // child
        printf("child : %d\n", getpid());
        sleep(3);
        exit(1);
    }
    while (1)
    {
        printf("father proc is doing some thing!\n");
        sleep(1);
    }
    return 0;
}
  • signal(SIGCHLD, handler);:这行代码使用 signal 函数来注册信号处理函数。SIGCHLD 是一个信号,它在子进程状态发生改变(比如子进程终止、暂停、继续等情况)时会发送给父进程。这里将 SIGCHLD 信号和自定义的 handler 函数关联起来,意味着当父进程收到 SIGCHLD 信号时,就会调用 handler 函数来处理相应情况。
  • pid_t cid; 定义了一个 pid_t 类型的变量 cid,用于存储后续 fork 函数返回的进程ID值。
  • if ((cid = fork()) == 0) 这是一个关键的条件判断语句,通过 fork 函数创建子进程:
    • fork 函数在父进程中返回新创建的子进程的进程ID(大于 0),在子进程中返回 0,如果创建子进程失败则返回 -1。这里判断 cid 是否等于 0,如果等于 0,说明当前代码执行的是子进程的逻辑分支。
    • 在子进程的逻辑中(也就是 if 条件成立的代码块):
      • 首先通过 printf 打印出自己的进程ID(printf("child : %d\n", getpid());),方便后续观察确认。
      • 然后调用 sleep 函数让子进程休眠 3 秒,模拟子进程执行一些任务的时间消耗。
      • 最后通过 exit 函数终止子进程,并返回状态值 1
  • 对于父进程(也就是 if 条件不成立,cid 大于 0 的情况),进入到后面的 while (1) 无限循环中:
    • 在这个循环里,每次循环都会通过 printf 打印出 father proc is doing some thing!,表示父进程正在进行一些操作,然后调用 sleep 函数暂停 1 秒再进入下一次循环,以此模拟父进程持续进行一些任务的过程。
  • 不过要注意的是,代码最后的 return 0; 其实在当前逻辑下是无法执行到的,因为父进程进入了一个无限循环,正常情况下不会跳出循环去执行这行返回语句。

makefile文件:

sig:sig.c 
	gcc -o sig sig.c  
.PHONY:clean 
clean: 
	rm -f sig

🚩总结

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI助力SEO优化的关键词策略解析

内容概要 在数字营销的快速发展中&#xff0c;人工智能&#xff08;AI&#xff09;正逐步成为提升搜索引擎优化&#xff08;SEO&#xff09;效果的重要工具。关键词策略是SEO成功的关键要素之一&#xff0c;而AI技术的应用使得这一过程更加高效和精准。在关键词研究中&#xf…

PHP-Casbin v4.0.0 发布,支持 ACL、RBAC、ABAC 等模型的访问控制框架

PHP-Casbin 是一个用 PHP 语言打造的轻量级开源访问控制框架&#xff0c;支持 ACL、RBAC、ABAC 多种模型。它采用了元模型的设计思想&#xff0c;支持多种经典的访问控制方案&#xff0c;如基于角色的访问控制 RBAC、基于属性的访问控制 ABAC 等。 更新内容&#xff1a; http…

解决Git中没有小绿勾与红叉叉的问题

一、检查自己的软件 必须安装Git和Tortoisegit&#xff08;也就是俗称的小乌龟&#xff09;这两个软件。 Git的下载地址&#xff1a; CNPM Binaries Mirrorhttps://registry.npmmirror.com/binary.html?pathgit-for-windows/ 寻找与自己电脑相配的软件版本就可以了。 Tor…

搭建跨境电商企业博客的指南

在跨境电商领域&#xff0c;企业博客不仅是展示品牌形象的窗口&#xff0c;也是连接全球客户的重要桥梁。一个精心搭建的企业博客能够提升品牌知名度、增强客户信任&#xff0c;并促进销售。 搭建企业博客的必要性 1. 建立品牌权威&#xff1a;通过高质量的内容&#xff0c;企…

渗透学习笔记(十一)Burp Suite 总结

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

课设CLion连接Ubuntu14makeQt项目出错解决汇总

在这之前需要注意以下几点&#xff1a; 1、需要 确保CLion能连接Ubuntu14 2、cmakelist.txt文件配置 3、知道部署路径&#xff1a; 问题一&#xff1a;/usr/bin/ld: cannot open output file GreedySnake: Is a directory 否则就会出现make以后应该生成一个可执行文件&…

【GO基础学习】gin的使用

文章目录 模版使用流程参数传递路由分组数据解析和绑定gin中间件 模版使用流程 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 1.创建路由r : gin.Default()// 2.绑定路由规则&#xff0c;执行的函数// gin.Context&#x…

磁编码器(Magnetic Encoder)

磁编码器&#xff08;Magnetic Encoder&#xff09;是一种传感器&#xff0c;它通过检测磁性材料的磁场变化来测量旋转或线性位置。编写用于读取磁编码器数据的C语言程序时&#xff0c;您需要根据具体的硬件接口和编码器类型进行调整。以下是一个基本的框架&#xff0c;假设我们…

Qt Creator项目构建配置说明

QT安装好之后&#xff0c;在安装目录的Tools\QtCreator\bin下找到qtcreator.exe文件并双击打开 点击文件-新建文件或项目 选择Qt Widgets Application 设置项目名称以及路径 make工具选择qmake&#xff08;cmake还未尝试过&#xff09; 设置主界面对应类的名称、父类&#…

智能边缘计算×软硬件一体化:开启全场景效能革命新征程(企业开发者作品)

边缘智能技术快速迭代&#xff0c;并与行业深度融合。它正重塑产业格局&#xff0c;催生新产品、新体验&#xff0c;带动终端需求增长。为促进边缘智能技术的进步与发展&#xff0c;拓展开发者的思路与能力&#xff0c;挖掘边缘智能应用的创新与潜能&#xff0c;高通技术公司联…

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…

Ps:创建数据驱动的图像

在设计实践中&#xff0c;常常需要处理大量内容变化但设计格式统一的任务&#xff0c;例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作&#xff0c;不仅耗时费力&#xff0c;还容易出错。 为解决这一问题&#xff0c;Photoshop 提供了强…

Kotlin 协程基础知识总结六 —— 协程 Flow 的综合应用

1、项目描述与搭建 &#xff08;P92~P94&#xff09;我们会将几个 Flow 的应用实例放在同一个 Demo 中&#xff0c;主页就是一个 Activity 里包含一个按钮&#xff0c;点击按钮跳转到对应的功能展示页面上。整体架构采用一个 Activity 多个 Fragment 的结构&#xff0c;结合 J…

环,域,体,整区,理想,极大理想,

环&#xff1a; 定义&#xff1a; 加法交换群 乘法半群 分配律 域的定义&#xff1a; 加法交换群 乘法群&#xff08;去掉0元是交换群&#xff09; 分配律 Eg:比如整数集合不是域&#xff0c;因为对于乘法来说&#xff0c;去掉0后没有单位元了&#xff0c;但是是环 Eg…

关于Flutter应用国际化语言的设置

目录 1. Locale配置 2. 用户切换/启动自动加载缓存里面的locale 由于最近在开发app国际化设置的时候遇到一些问题&#xff0c;所以做出一些总结。 1. Locale配置 具体的初始化配置可以参考文档&#xff1a;i18n | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 值得…

【游戏开发】游戏生产的标准与工业化,管线Pipeline的概念与设计(项目管理,资产管理)

【游戏开发】游戏生产的标准与工业化&#xff0c;管线Pipeline的概念与设计&#xff08;项目管理&#xff0c;资产管理&#xff09; 文章目录 1、管线&#xff08;Pipeline&#xff09;是什么&#xff1f;1.1 管线解决什么问题&#xff08;例子&#xff09;1.2 一个动画电影的完…

探寻 OneCode 核心优势:MVVM 进阶与前后端协同之魅

在当今的软件开发领域&#xff0c;高效、可维护且功能强大的架构是开发者们不懈追求的目标。OneCode 凭借其独特的增强版 MVVM 架构、前后端一体化特性&#xff0c;以及创新的技术如 OneCode DSM&#xff08;Domain-Specific Modeling&#xff0c;领域特定建模&#xff09;、视…

机器人C++开源库The Robotics Library (RL)使用手册(三)

进入VS工程,我们先看看这些功能函数及其依赖库的分布关系: rl命名空间下,主要有八大模块。 搞定VS后将逐个拆解。 1、编译运行 根据报错提示,配置相应错误的库(根据每个人安装位置不同而不同,我的路径如下:) 编译所有,Release版本耗时大约10分钟。 以rlPlan运动…

ISP代理与住宅代理的区别

了解ISP代理 通常称为互联网服务提供商代理&#xff0c;通过服务提供商将用户直接连接到互联网。这些代理利用互联网服务提供商的网络&#xff0c;通常提供广泛的IP地址池。ISP代理通常快速可靠&#xff0c;非常适合一般浏览和常规互联网使用场景。 了解住宅代理 相比之下&a…

【ArcGIS Pro】完整的nc文件整理表格模型构建流程及工具练习数据分享

学术科研啥的要用到很多数据&#xff0c;nc文件融合了时间空间数据是科研重要文件。之前分享过怎样将nc文件处理成栅格后整理成表格。小编的读者还是有跑不通整个流程的&#xff0c;再来做一篇总结篇&#xff0c;也分享下练习数据跟工具&#xff0c;如果还是弄不了的&#xff0…