Linux编程:3、进程通信-信号

一、进程通信概述

(一)进程通信的目的

在企业开发中,一个项目常常需要多个进程共同协作,而这些进程之间需要进行通信(交换信息)以便协作。本章内容主要围绕信号讲解,其它进程通信的常用方式请期待后续文章的发布

(二)进程通信的常用方式

  1. 信号
  2. 信号量
  3. 匿名管道
  4. 命名管道
  5. 共享内存
  6. 消息队列
  7. 本地套接字

二、信号的基本概念

(一)信号的定义

在 Linux 编程中,信号(Signal)是一种异步通信机制,用于通知进程系统中发生了某种事件。它类似于软件中断,可打断进程的正常执行流,使其处理特定事件。

(二)信号的快速入门实例

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void signal_handler(int arg) {printf("Received signal: %d\n", arg);
}int main(void) {int count = 1;signal(SIGINT, signal_handler);while (1) {printf("working...%d\n", count++);sleep(1);}return 0;
}

程序启动后,按下ctrl + c会向当前进程发送SIGINT信号,触发signal_handler处理函数。 


三、信号的分类

这里我只显示常用的,不常用的信号如果你们遇到了问一下AI就行了

(一)非实时信号(1-31)

  1. 特点:不支持排队,可能造成信号丢失。

  2. 常见非实时信号

  3. 信号属性值默认处理方式定义描述
    SIGHUP1Term用户终端连接结束时发出
    SIGINT2Term键盘输入Ctrl+c时发出,通知前台进程
    SIGKILL9Term程序员使用kill -9指令发出
    SIGCHLD17Ign子进程结束时父进程收到的信号
    SIGSTOP19Stop停止进程执行(暂停不结束)
    SIGTSTP20Stop键盘按下Ctrl+Z时发出
  4. 处理方式

    • Term:终止进程
    • Ign:忽略信号
    • Core:终止进程并产生 core dump 文件
    • Stop:暂停进程
    • Continue:让停止的进程继续执行至

(二)实时信号(32-64)(不常用

  1. 特点:支持排队,不会造成信号丢失。
  2. 范围:从SIGRTMIN(34)到SIGRTMAX(64),如SIGRTMIN+1SIGRTMIN+2等。

四、信号的发送方式

(一)自动发送

例如在终端按下ctrl + c,会自动向前台进程发送SIGINT信号至。

(二)使用 kill 系统调用

  1. 函数原型int kill(pid_t pid, int sig);
  2. 功能:向指定进程(pid)发送指定信号(sig),成功返回 0,失败返回 - 1 至。
  3. 代码:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    int main(void)
    {pid_t pid = fork();if (pid < 0) {perror("fork failed.");exit(1);}if (pid == 0) {int count = 1;while (1) {printf("child process worked. %d\n", count++);sleep(1);}}else {int n;while (1) {printf("\nPlease select: 1)Stop child process 2)Continue child ""process 3)Killchild process\n");scanf("%d", &n);switch (n) {case 1:kill(pid, SIGSTOP);break;case 2:kill(pid, SIGCONT);break;case 3:kill(pid, SIGKILL);break;default:break;}if (n == 3) {int status;waitpid(pid, &status, 0);  // 等待子进程结束并回收子进程break;}}}return 0;
    }

(三)使用 kill 命令

  1. 本质:kill 命令的内部实现调用了 kill 系统调用。
  2. 示例kill -9 2483 相当于pid = 2483,调用了kill(2483, SIGKILL)函数

五、信号的处理方式

(一)signal 函数

这个函数不如sigaction安全,建议编程时尽量用sigaction,代码演示在信号屏蔽之后

  1. 函数原型sighandler_t signal(int signum, sighandler_t handler);
  2. 参数
    • signum:除SIGKILLSIGSTOP外的任意信号
    • handler:可以是SIG_IGN(忽略信号)、SIG_DFL(恢复默认处理)或自定义处理函数指针
  3. 返回值:成功返回上一次的 handler,失败返回SIG_ERR至。

(二)sigaction 函数

  1. 优势:比signal更健壮。
  2. 函数原型int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  3. 结构体sigaction
    struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);
    };
  4. sa_flags常用选项
    • SA_RESTART:被信号打断的系统调用自动重新发起
    • SA_NOCLDSTOP:子进程暂停 / 继续时父进程不接收SIGCHLD
    • SA_SIGINFO:使用sa_sigaction作为处理函数至。

六、信号屏蔽字与信号集操作

(一)信号屏蔽字的处理

  1. 默认处理:当信号处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,处理结束后恢复至。
  2. 自定义处理函数int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    • howSIG_BLOCK(阻塞信号集)、SIG_UNBLOCK(解除阻塞)、SIG_SETMASK(设置新屏蔽集)至。

(二)信号集相关函数

  1. sigemptyset(sigset_t *set):初始化信号集为空
  2. sigfillset(sigset_t *set):初始化信号集包含所有信号
  3. sigaddset(sigset_t *set, int signum):添加信号到信号集
  4. sigdelset(sigset_t *set, int signum):从信号集删除信号
  5. sigismember(const sigset_t *set, int signum):判断信号是否在集合中至。

七、代码演示 

#include <signal.h>   // 包含信号处理相关函数声明,如sigaction、sigprocmask等
#include <stdio.h>    
#include <stdlib.h>   
#include <unistd.h>   // 包含Unix系统函数,如sleep、fork等// 信号处理函数,当接收到信号时被调用
void sig_handler(int signum)
{printf("Received signal: %d\n", signum);  // 打印接收到的信号编号
}int main(void)
{struct sigaction act;  // 定义sigaction结构体,用于设置信号处理方式act.sa_handler = sig_handler;  // 设置信号处理函数为sig_handleract.sa_flags   = 0;  // 清空标志位,使用默认处理行为// 清空信号屏蔽集,确保初始时不屏蔽任何信号sigemptyset(&act.sa_mask);// 设置SIGINT信号的处理方式为act中定义的处理方式sigaction(SIGINT, &act, 0);  printf("5 秒后,将屏蔽信号 SIGINT\n");// 倒计时5秒,期间可接收SIGINT信号for (int i = 5; i >= 1; i--) {printf("%d\n", i);sleep(1);}// 初始化信号集mask并将SIGINT添加到其中sigset_t mask;sigemptyset(&mask);sigaddset(&mask, SIGINT);// 阻塞mask中的信号(SIGINT),并保存原来的信号屏蔽字sigset_t old_mask;sigprocmask(SIG_BLOCK, &mask, &old_mask);printf("已经将 SIGINT 添加到信号集\n");// 检查是否有悬而未决的信号(即被阻塞但未处理的信号)sigset_t pend_mask;sigpending(&pend_mask);if (sigismember(&pend_mask, SIGINT)) {printf("SIGINI 被挂起了\n");}printf("5 秒后,将恢复信号屏蔽字\n");// 倒计时5秒,期间SIGINT信号会被阻塞for (int i = 5; i >= 1; i--) {printf("%d\n", i);sleep(1);}// 恢复之前保存的信号屏蔽字,解除对SIGINT的阻塞sigprocmask(SIG_SETMASK, &old_mask, 0);printf("信号屏蔽字已恢复\n");while (1) {sleep(1);}return 0;
}

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

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

相关文章

深度解析Vue.js组件开发与实战案例

一、Vue.js组件化思想 Vue.js的核心思想之一就是组件化开发。组件系统是Vue的一个重要概念,它允许我们使用小型、独立和通常可复用的组件构建大型应用。在Vue中,组件本质上是一个拥有预定义选项的Vue实例。 1.1 为什么需要组件化 代码复用:避免重复造轮子,提高开发效率可…

TensorFlow 2.0 与 Python 3.11 兼容性

TensorFlow 2.0 与 Python 3.11 兼容性 TensorFlow 2.0 官方版本对 Python 3.11 的支持有限&#xff0c;可能出现兼容性问题。建议使用 TensorFlow 2.10 或更高版本&#xff0c;这些版本已适配 Python 3.11。若需强制运行&#xff0c;可通过以下方式解决依赖冲突&#xff1a; …

MyBatisPlus 全面学习路径

MyBatisPlus 全面学习路径 学习目录 第一部分&#xff1a;MyBatisPlus 基础 MyBatisPlus 简介与核心特性快速入门与环境搭建核心功能&#xff1a;BaseMapper 与 CRUD 接口条件构造器&#xff08;Wrapper&#xff09;详解ActiveRecord 模式主键策略与通用枚举 第二部分&…

React16,17,18,19更新对比

文章目录 前言一、16更新二、17更新三、18更新四、19更新总结 前言 总结react 16&#xff0c;17&#xff0c;18&#xff0c;19所更新的内容&#xff0c;并且部分会涉及到原理讲解。 一、16更新 1、在16.8之前更新&#xff0c;还是基于class组件的升级和维护更新。并且更新了一…

【git】有两个远程仓库时的推送、覆盖、合并问题

当你执行 git pull origin develop(或默认的 git pull)时,Git 会把远端 origin/develop 的提交合并到你本地的 develop,如果远端已经丢掉(或从未包含)你之前在私库(priv)里提交过的改动,那这些改动就会被「覆盖」,看起来就像「本地修改没了」。 要解决这个问题,分…

Spring Boot 集成国内AI,包含文心一言、通义千问和讯飞星火平台实战教程

Spring Boot 集成国内AI&#xff0c;包含文心一言、通义千问和讯飞星火平台实战教程 一、项目结构二、添加Maven依赖三、配置API密钥 (application.yml)四、配置类1. AI配置类 (AiProperties.java)2. 启用配置类 (AiConfig.java) 五、服务层实现1. 文心一言服务 (WenxinService…

Elastic Search 学习笔记

1. Elasticsearch 是什么&#xff1f;有哪些应用场景&#xff1f; Elasticsearch 整体原理流程&#xff1f; Elasticsearch 是一个为海量数据提供近实时搜索和分析能力的分布式搜索引擎&#xff0c;广泛应用于全文检索、日志分析和大数据处理场景中。 Elasticsearch 整体原理…

动态规划之斐波那契数(一)

解法一&#xff1a;递归 class Solution { public:int fib(int n) {if(n<2) return n;return fib(n-1)fib(n-2);} }; 解法二&#xff1a;dp class Solution { public:int fib(int N) {if (N < 1) return N;int dp[2];dp[0] 0;dp[1] 1;for (int i 2; i < N; i) {…

如何设置爬虫的访问频率?

设置爬虫的访问频率是爬虫开发中的一个重要环节&#xff0c;尤其是在爬取大型网站&#xff08;如1688&#xff09;时&#xff0c;合理的访问频率可以避免对目标网站造成过大负担&#xff0c;同时也能降低被封禁的风险。以下是一些常见的方法和建议&#xff0c;帮助你合理设置爬…

前端面试六之axios

一、axios简介 Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js 环境。在浏览器端&#xff0c;Axios 的底层实现是基于原生的 XMLHttpRequest&#xff08;XHR&#xff09;。它对 XHR 进行了封装&#xff0c;增加了 Promise 支持、自动转换 JSON 数据…

模板方法模式Template Method Pattern

模式定义 定义一个操作中算法的骨架&#xff0c;而将一些步骤延迟到子类中&#xff0c;模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 类行为型模式 模式结构 AbstractClass&#xff1a;抽象类ConcreteClass&#xff1a;具体子类 只有类之间的继…

【行云流水AI笔记】游戏里面的强化学习使用场景

强化学习在游戏中的应用已从早期的棋类博弈扩展到现代复杂游戏的全流程优化&#xff0c;以下是结合最新技术进展的核心应用场景及典型案例&#xff1a; 一、竞技游戏的策略突破 1. 策略博弈类游戏 代表案例&#xff1a;AlphaGo/AlphaZero&#xff08;围棋&#xff09;、Alph…

使用Python和PyTorch框架,基于RetinaNet模型进行目标检测,包含数据准备、模型训练、评估指标计算和可视化

下面是一个完整的实现方案,使用Python和PyTorch框架,基于RetinaNet模型进行目标检测,包含数据准备、模型训练、评估指标计算和可视化。 import os import numpy as np import matplotlib.pyplot as plt import torch import torchvision from torchvision.models.detection…

springboot服务如何获取pod当前ip方案及示例

在 Kubernetes 集群中&#xff0c;Spring Boot 服务获取 Pod 当前 IP 的方案主要有两种&#xff1a;通过环境变量注入 或 通过 Java 代码动态获取网络接口 IP。以下是两种方案的详细说明及示例&#xff1a; 方案一&#xff1a;通过 Kubernetes Downward API 注入环境变量 原理…

1.MySQL三层结构

1.所谓安装的Mysql数据库&#xff0c;就是在电脑上安装了一个数据库管理系统&#xff08;【DBMS】database manage system&#xff09;&#xff0c;这个管理程序可以管理多个数据库。 2.一个数据库中可以创建多个表&#xff0c;以保存数据&#xff08;信息&#xff09;。【数据…

[深度学习]目标检测基础

目录 一、实验目的 二、实验环境 三、实验内容 3.1 LM_BoundBox 3.1.1 实验代码 3.1.2 实验结果 3.2 LM_Anchor 3.2.1 实验代码 3.2.2 实验结果 3.3 LM_Multiscale-object-detection 3.3.1 实验代码 3.3.2 实验结果 四、实验小结 一、实验目的 了解python语…

ALOHA机器人平台:低成本、高精度双臂操作及其进展深度解析

原创1从感知决策到具身智能的技术跃迁与挑战(基座模型与VLA模型)2ALOHA机器人平台&#xff1a;低成本、高精度双臂操作及其进展深度解析3(上)通用智能体与机器人Transformer&#xff1a;Gato和RT-1技术解析及与LLM Transformer的异同4(下)通用智能体与机器人Transformer&#x…

C++: 类 Class 的基础用法

&#x1f3f7;️ 标签&#xff1a;C、面向对象、类、构造函数、成员函数、封装、继承、多态 &#x1f4c5; 更新时间&#xff1a;2025年6月15日 &#x1f4ac; 欢迎在评论区留言交流你的理解与疑问&#xff01; 文章目录 前言一、什么是类&#xff1f;二、类的定义1.基本语法2.…

Java EE与Jakarta EE命名空间区别

在 Java 生态中&#xff0c;javax 和 jakarta 代表了 企业级 Java 规范&#xff08;Java EE/Jakarta EE&#xff09;的命名空间演进&#xff0c;核心区别在于归属权和管理组织的变更。以下是详细对比&#xff1a; 1. 历史背景 javax&#xff1a; 源自 Java EE&#xff08;Java …

2 Studying《Arm A715 Technical Reference Manual》

目录 2. The Cortex‑A715 core 2.1 Cortex‑A715 core features 2.2 Cortex‑A715 core confifiguration options 2.3 DSU-110 dependent features 2.4 Supported standards and specifications 2.6 Design tasks 3. Technical overview 3.1 Core components 3.2 Int…