【Linux】fork和exec中的信号继承探索

news2024/11/18 9:53:04

fork和exec中的信号继承探索

  • 一、结论
  • 二、代码验证
    • 2.1 代码编写
    • 2.2 代码执行
  • 三、linux源码验证
  • 四、APUE中的验证
  • 五、其他

一、结论

  1. fork时子进程会继承父进程的信号处理方式,包括父进程设置信号为SIG_DFLSIG_IGN或捕获后设置自定义处理函数。
  2. exce时子进程会继承父进程设置为SIG_DFLSIG_IGN的信号。对于捕获后设置自定义处理函数的信号则不继承这个处理函数。

二、代码验证

2.1 代码编写

此处针对exec的情况进行验证,对于单纯fork后的情况不进行说明。

  1. 编写main.c。此处捕获SIGCHLD自定义handle处理方式。当main函数执行后,将fork子进程,同时子进程会exec加载son可执行程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

void handler(int sig) {
    int status;
	int pid = waitpid(-1, &status, WNOHANG);
	if (pid > 0) {
		printf(">>>>>>>>>>>>>>>A child process has exited, pid: %d\n", pid);
	}
}

int main() {
	// 设置信号处理函数
    signal(SIGCHLD, handler);

    pid_t pid = fork();
    if (pid == -1) {
        // fork失败
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程
		sleep(3);
		execlp("./son", "son", NULL);
    } else {
        // 父进程继续执行,不等待子进程
        while(1) {
            printf("Parent process, PID: %d, son PID: %d\n", getpid(), pid);
            sleep(3);
        }
    }
    return 0;
}

执行 gcc main.c -o main 进行编译

  1. 编写son.c,调用fork创建孙子,孙子进程创建后会exec加载grandson可执行程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    pid_t pid = fork();
    if (pid == -1) {
        // fork失败
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程
		sleep(3);
		execlp("./grandson", "grandson", NULL);
    } else {
        // 父进程继续执行,不等待子进程
        while(1) {
            printf("son process, PID: %d, grandson PID: %d\n", getpid(), pid);
            sleep(3);
        }
    }
    return 0;
}

执行 gcc son.c -o son 进行编译

  1. 编写grandson.c,代码中定期输出语句,类比执行业务代码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    while(1){
        printf("I am grandson, running!..., pid=%d\n", getpid());
        sleep(3);
    }
    return 0;
}

执行 gcc grandson.c -o grandson 进行编译

2.2 代码执行

输入 ./main 执行程序,首先会观察到有两个 ./main程序,业务此时fork了
在这里插入图片描述
三秒后500721号进程会执行exec,替换为son程序。son程序加载后会fork一次,故此时有两个son进程
在这里插入图片描述
三秒后500770号进程会执行exec,替换为grandson程序。此时有main,son和grandson进程存在
在这里插入图片描述
当孙子进程退出时(执行kill -9杀死),它将会变为僵尸进程,因为它的父进程即son进程没有调用wait,waitpid或忽略SIGCHLD信号
在这里插入图片描述
结论:验证了父进程捕获信号后自定义处理逻辑,是不继承到子进程的。

此外,当我们将main.c的signal(SIGCHLD, handler);替换为signal(SIGCHLD, SIG_IGN);后,按上述流程执行,杀死孙子进程时,现象如下:
在这里插入图片描述
一旦执行杀死孙子进程,则ps检测不到了,证明它被真正杀死,而不会陷入僵尸状态。

结论:验证了父进程忽略某个信号后,会继承到子进程,子进程同样忽略此信号。

三、linux源码验证

此处从源码角度论证fork时子进程会继承父进程的信号处理方式,包括父进程设置信号为SIG_DFLSIG_IGN或捕获后设置自定义处理函数。
阅读fork.c源码可知:
copy_process函数调用copy_sighand函数&copy_signal函数

在这里插入图片描述

  1. 信号处理函数的继承:在copy_process函数中,当创建新进程(线程)时,如果clone_flags中设置了CLONE_SIGHAND,则共享信号处理函数。如果没有设置,则会复制父进程的信号处理函数。这可以通过copy_sighand函数实现,该函数通过memcpy复制信号处理动作,即sig->action。
  2. 信号状态的复制:在copy_signal函数中,如果clone_flags中没有设置CLONE_THREAD,则会为新进程分配一个新的signal_struct结构体,并且复制父进程的信号限制和一些其他的信号状态。

四、APUE中的验证

  1. 本文的结论1为:fork时子进程会继承父进程的信号处理方式,包括父进程设置信号为SIG_DFLSIG_IGN或捕获后设置自定义处理函数。APUE对结论1的阐述如下:

在这里插入图片描述

  1. 本文的结论2为:exce时子进程会继承父进程设置为SIG_DFLSIG_IGN的信号。对于捕获后设置自定义处理函数的信号则不继承这个处理函数。APUE对结论2的阐述如下:

在这里插入图片描述

五、其他

上文探究了fork和exec对信号的继承情况,那么对于fd的继承情况如何呢?有待后续探索…

ref:
https://www.cnblogs.com/yiyide266/p/13706799.html
《UNIX环境高级编程》

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

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

相关文章

有些错误,常犯常新、常新常犯:记录一个使用element-plus的tooltip组件的错误

使用element-plus的tooltip组件&#xff0c;最开始的写法是这样的&#xff1a; <el-tooltipclass"box-item"effect"dark"content"tooltip content" ><el-button v-if"isDisabled" :underline"false" type"pr…

一文扫尽Nas常用Docker软件

NAS&#xff08;Network Attached Storage&#xff0c;网络附加存储&#xff09;设备上的Docker软件选择取决于您的具体需求和用途。以下是一些NAS上常用的Docker软件推荐&#xff1a; Docker管理工具&#xff1a; Watchtower&#xff1a;它可以自动更新Docker容器中的镜像&…

从零开始学Vue3--环境搭建

1.搭建环境 下载nodejs nodejs下载地址 更新npm npm install -g npm 设置npm源&#xff0c;加快下载速度 npm config set registry https://registry.npmmirror.com 使用脚手架创建项目 npm create vuelatest 根据你的需要选择对应选项 进入新建的项目下载依赖 npm in…

kaggle竞赛实战3

接前文&#xff0c;本文主要做以下几件事&#xff1a; 1、把前面处理完的几个表拼成一个大表 2、做特征衍生&#xff08;把离散特征和连续特征两两组合得出&#xff09; # In[89]: #开始拼接表 transaction pd.concat([new_transaction, history_transaction], axis0, ignor…

STM32 USART的字符编码(发送器的实现逻辑)

目录 概述 1 字符编码 1.1 USART 字符说明 1.2 字长编程 2 发送器 2.1 字符发送 2.2 可配置的停止位 2.3 配置停止位方法 3 单字节通信 4 中断字符 5 空闲字符 概述 本文主要讲述STM32 USART的发送端功能实现的原理&#xff0c;包括字节编码长度&#xff0c;发送器…

Cyber Weekly #8

赛博新闻 1、微软召开年度发布会Microsoft Build 2024 本周&#xff08;5.22&#xff09;微软召开了年度发布会&#xff0c;Microsoft Build 2024&#xff0c;发布了包括大杀器 Copilot Studio 在内的 50 项更新。主要包括&#xff1a; 硬件层面&#xff1a;与英伟达 & A…

网络空间安全数学基础·群

重点&#xff1a; 1. 群及子群的定义及相关结论 2. 群的判断,子群的判断 3. 群的阶,元素的阶,它们的相互关系 4. 同态,同构,核子群 2.1群的定义 定义&#xff1a;设G是一非空集合。如果在G上定义了一个代数运算&#xff0c;称为乘法&#xff0c;记为ab&#xff0c;而且这个运…

【STL】C++ vector基本使用

目录 一 vector常见构造 1 空容器构造函数&#xff08;默认构造函数&#xff09; 2 Fill 构造函数 3 Range 构造函数 4 拷贝构造函数 5 C11构造 二 vector迭代器 1 begin && end 2 rbegin && rend 3 补充排序 三 vector 容量操作 1 size 2 resize …

进程信号(1)

目录 一、信号 1.1、生活中的信号 1.2、Linux中的信号 二、信号处理常见方式 三、信号的产生 3.1、简单理解信号的保存和发送 3.2、键盘产生信号 3.3、核心转储 3.4、系统调用接口产生信号 3.4.1、kill 3.4.2、raise 3.4.3、abort 3.5、软件条件产生信号 3.6、硬…

【操作系统】发展与分类(手工操作、批处理、分时操作、实时操作)

2.操作系统发展与分类 思维导图 手工操作阶段&#xff08;此阶段无操作系统&#xff09; 需要人工干预 缺点&#xff1a; 1.用户独占全机&#xff0c;资源利用率低&#xff1b; 2.CPU等待手工操作&#xff0c;CPU利用不充分。 批处理阶段&#xff08;操作系统开始出现&#x…

firewalld 防火墙

firewalld概述 Linux系统防火墙从CentOS7开始的默认防火墙工作在网络层&#xff0c;属于包过滤防火墙 Firewalld和iptables的关系 netfilter 位于Linux内核中的包过滤功能体系称为Linux防火墙的“内核态” firewalld Centos默认的管理防火墙规则的工具称为防火墙的“用…

【C++】右值引用 移动语义

目录 前言一、右值引用与移动语义1.1 左值引用和右值引用1.2 右值引用使用场景和意义1.3 右值引用引用左值及其一些更深入的使用场景分析1.3.1 完美转发 二、新的类功能三、可变参数模板 前言 本篇文章我们继续来聊聊C11新增的一些语法——右值引用&#xff0c;我们在之前就已…

sqli-lib4-6关教程

SERIES-4 输入?id1 输入?id2-1&#xff0c;说明该数据类型为字符型 输入?id1’ 输入?id1"&#xff0c;说明闭合符号为" 输入?id1")– 输入?id1") order by 3– 输入?id1") order by 4– 数据共三列&#xff0c;输入?id-1") union selec…

InfLLM的笔记

文件中提供的代码是一个Python函数chat_loop&#xff0c;它是聊天系统的核心循环。以下是对这段代码逻辑的梳理&#xff1a; 函数定义与参数 chat_loop函数接收多个参数&#xff0c;用于配置聊天模型和聊天环境。参数包括模型路径、设备类型、GPU数量、最大GPU内存、数据类型…

K8s的kubectl的基本操作

K8s的kubectl的基本操作 K8s基本信息的查看 查看版本信息 kubectl versio查看资源对象简写 kubectl api-resources查看集群信息 kubectl cluster-info配置kubectl自动补全 source <(kubectl completion bash)查看master节点状态 kubectl get cs查看命名空间 kubectl…

Elastic Cloud 将 Elasticsearch 向量数据库优化配置文件添加到 Microsoft Azure

作者&#xff1a;来自 Elastic Serena Chou, Jeff Vestal, Yuvraj Gupta 今天&#xff0c;我们很高兴地宣布&#xff0c;我们的 Elastic Cloud Vector Search 优化硬件配置文件现已可供 Elastic Cloud on Microsoft Azure 用户使用。 此硬件配置文件针对使用 Elasticsearch 作…

<el-table>根据后端返回数据决定合并单元格的数量(521特别版)

文章目录 一、需求说明二、用到的方法三、代码&#xff08;只展示了本文章重点代码&#xff09; 一、需求说明 &#x1f49d;仅合并第一列&#xff0c;其余为固定列 二、用到的方法 &#x1f48c;合并单元格可以采用三种方法 &#x1f495;1. 手写表格 简单 但没有饿了么写…

力扣HOT100 - 136. 只出现一次的数字

解题思路&#xff1a; class Solution {public int singleNumber(int[] nums) {int single 0;for (int num : nums) {single ^ num;}return single;} }

生命在于学习——Python人工智能原理(1.1)

说明&#xff1a;今年学一部分人工智能方向的知识&#xff0c;网安也会穿插&#xff0c;看后续如何将二者结合起来。 一、人工智能的基本知识 1、人工智能的起源 1956年美国达特茅斯学院召开了一个夏季论班&#xff0c;首次提出人工智能的概念。 1950年图灵提出了图灵测试&a…

Jenkins + github 自动化部署配置

1 Jenkins安装 AWS EC2安装Jenkins&#xff1a;AWS EC2 JDK11 Jenkins-CSDN博客 AWS EC2上Docker安装Jenkins&#xff1a;https://blog.csdn.net/hhujjj2005/article/details/139078402 2 登录jenkins http://192.168.1.128:8080/ $ docker exec -it d1851d9e3386 /bin/ba…