当前位置: 首页 > news >正文

Linux学习-通信(信号,共享内存)

信号(Signal)

(一)本质与核心价值

信号是 Linux 系统中进程间异步通信的“软中断”机制,核心解决:

  • 进程控制:如终止、暂停、恢复进程(SIGINT/SIGSTOP/SIGCONT)。
  • 异常处理:捕获非法操作(SIGSEGV 段错误、SIGPIPE 管道破裂)。
  • 异步通知:子进程结束通知父进程(SIGCHLD)、定时任务触发(SIGALRM)等。

特点:异步性(接收方无法预测信号何时到达)、抢占性(打断当前代码流优先处理信号)。

(二)系统信号全量清单(kill -l 输出)

通过 kill -l 可查看系统支持的 64 个信号(不同系统可能有差异),按功能分类关键信号:

1. 常用基础信号(1~31 为非实时信号,32~64 为实时信号 SIGRTMIN~SIGRTMAX
信号编号信号名触发场景/默认行为关键特性
1SIGHUP终端断开、进程组领导权变化常用于“重启配置”(如 nginx 重载)
2SIGINTCtrl + c 触发中断进程,默认终止
3SIGQUITCtrl + \ 触发终止进程并生成 core dump
4SIGILL非法指令执行(如二进制文件格式错误)进程崩溃,默认终止
5SIGTRAP调试陷阱(如 gdb 断点触发)调试专用,默认终止
6SIGABRT进程主动调用 abort()强制终止并生成 core dump
7SIGBUS总线错误(如内存对齐违规)进程崩溃,默认终止
8SIGFPE浮点运算错误(除零、溢出等)进程崩溃,默认终止
9SIGKILLkill -9 强制发送强制终止,无法被捕获/忽略
10SIGUSR1用户自定义信号需编程捕获,实现自定义逻辑
11SIGSEGV非法内存访问(越界、空指针)进程崩溃(段错误),默认终止
12SIGUSR2用户自定义信号需编程捕获,实现自定义逻辑
13SIGPIPE管道写端关闭后仍写操作进程崩溃(管道破裂),默认终止
14SIGALRMalarm() 定时触发或系统定时任务定时通知,默认终止
15SIGTERMkill 默认信号(kill -15优雅终止进程,可捕获处理
16SIGSTKFLT栈溢出(老式架构,现代系统少用)进程崩溃,默认终止
17SIGCHLD子进程退出、暂停或继续通知父进程回收子进程
18SIGCONT显式发送或作业控制恢复恢复暂停态进程执行
19SIGSTOP强制暂停(kill -19暂停进程,无法被捕获/忽略
20SIGTSTPCtrl + z 触发暂停进程(终端停止信号)
21SIGTTIN后台进程读终端暂停进程,默认终止
22SIGTTOU后台进程写终端暂停进程,默认终止
23SIGURG套接字紧急数据到达通知进程处理紧急数据
24SIGXCPU进程 CPU 时间超过限制进程崩溃,默认终止
25SIGXFSZ文件大小超过系统限制进程崩溃,默认终止
26SIGVTALRM虚拟时钟定时(按进程 CPU 时间计时)定时通知,默认终止
27SIGPROF剖析时钟定时(含内核时间)性能分析工具常用
28SIGWINCH终端窗口大小变化通知进程调整输出格式
29SIGIO异步 I/O 事件通知高性能 I/O 模型(如 epoll
30SIGPWR电源状态变化(如电池低电量、断电)通知进程处理电源事件
31SIGSYS系统调用参数错误(如调用未实现的系统调用)进程崩溃,默认终止
2. 实时信号(SIGRTMIN ~ SIGRTMAX
  • 编号:32~64(具体数量因系统而异,如 SIGRTMIN 可能是 34,需 kill -l 确认)。
  • 特点:高优先级(比普通信号先处理)、可排队(避免信号丢失)、用户可控(常用于实时系统、低延迟通知场景)。

(三)信号处理流程与编程

1. 信号处理方式

进程对信号有三种响应策略:

  • 缺省(SIG_DFL:按系统默认行为处理(如 SIGINT 默认终止进程)。
  • 忽略(SIG_IGN:不处理信号(如忽略 SIGCHLD 需自己回收子进程)。
  • 捕获(自定义函数):注册回调函数,信号触发时执行自定义逻辑。
2. 核心函数:signal
  • 头文件:#include <signal.h>
  • 原型:
    typedef void (*sighandler_t)(int);  
    sighandler_t signal(int signum, sighandler_t handler);  
    
  • 作用:注册信号处理函数(绑定信号 signum 与处理逻辑 handler)。
  • 参数:
    • signum:信号编号(如 SIGINT)。
    • handler:处理方式(SIG_IGN/SIG_DFL 或自定义函数地址)。
  • 返回值:
    • 成功:返回之前的信号处理函数(首次注册返回 SIG_DFL)。
    • 失败:返回 SIG_ERR(需检查 errno)。

示例:捕获 SIGINT 并自定义处理:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handle_sigint(int signum) {printf("捕获到信号:%d(SIGINT),进程继续运行...\n", signum);
}int main() {// 注册信号处理函数if (signal(SIGINT, handle_sigint) == SIG_ERR) {perror("signal");return 1;}printf("进程启动,按 Ctrl + c 测试信号捕获...\n");while (1) {sleep(1); // 模拟业务逻辑}return 0;
}

(四)信号发送与控制

1. 命令行发送信号:kill 命令
  • 语法:kill -[信号编号/名称] 进程PID
    • 示例:
      • kill -9 1234:强制终止 PID 为 1234 的进程(发送 SIGKILL)。
      • kill -SIGUSR1 5678:给 PID 5678 发送 SIGUSR1 信号。
2. 编程发送信号函数
函数名作用关键参数示例(简化)
kill给指定进程发信号pid_t pid, int sigkill(1234, SIGINT);
raise给自己所在进程发信号int sigraise(SIGALRM);
alarm定时发送 SIGALRM 信号unsigned int secondsalarm(5);(5 秒后发 SIGALRM
pause挂起进程,等待信号唤醒-pause();(被信号打断后继续)

共享内存(Shared Memory)

(一)核心价值

进程间通信(IPC)效率最高的方式,原理:

  1. 内核开辟一块共享内存区域,多个进程通过内存映射将其映射到自己的虚拟地址空间。
  2. 进程直接读写内存地址完成数据交换,跳过“内核-用户空间”的拷贝(如管道、消息队列需两次拷贝)。

适合场景:大数据量、低延迟的进程协作(如多进程并行计算、游戏服务器进程间同步)。

(二)操作流程与函数(6 步完整周期)

1. 创建 IPC Key:ftok
  • 头文件:#include <sys/types.h>#include <sys/ipc.h>
  • 原型:key_t ftok(const char *pathname, int proj_id);
  • 作用:生成唯一的 IPC 键值,用于标识共享内存(不同进程需用相同 pathnameproj_id 生成相同 key)。
  • 参数:
    • pathname:存在的文件路径(如 "/tmp"),建议用固定文件避免冲突。
    • proj_id:项目 ID(1~255 的整数,如 'A' 等价于 65)。
  • 返回值:
    • 成功:返回 key_t 类型的键值。
    • 失败:返回 -1(检查 errno,如文件不存在、权限不足)。
2. 创建共享内存:shmget
  • 头文件:#include <sys/types.h>#include <sys/shm.h>
  • 原型:int shmget(key_t key, size_t size, int shmflg);
  • 作用:向内核申请共享内存,返回 共享内存 ID(后续操作的标识)。
  • 参数:
    • keyftok 生成的键值。
    • size:共享内存大小(字节),自动对齐为系统页大小(如 4096 字节的整数倍)。
    • shmflg:权限标志(如 IPC_CREAT | 0664IPC_CREAT 表示不存在则创建,0664 是权限)。
  • 返回值:
    • 成功:返回共享内存 ID(非负整数)。
    • 失败:返回 -1(检查 errno,如权限不足、内存不足)。
3. 映射共享内存到用户空间:shmat
  • 头文件:#include <sys/types.h>#include <sys/shm.h>
  • 原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 作用:将内核共享内存映射到进程的虚拟地址空间,返回可直接读写的内存指针
  • 参数:
    • shmidshmget 返回的共享内存 ID。
    • shmaddr:期望的映射地址(填 NULL 让系统自动分配)。
    • shmflg:权限(SHM_RDONLY 只读;0 读写,需配合内存权限)。
  • 返回值:
    • 成功:返回映射后的内存首地址(void * 类型)。
    • 失败:返回 (void *)-1(检查 errno,如权限不足)。
4. 读写共享内存
  • 直接通过 shmat 返回的指针操作内存,如:
    char *shm_ptr = shmat(shmid, NULL, 0);  
    if (shm_ptr != (void *)-1) {  // 写数据  sprintf(shm_ptr, "Hello, Shared Memory!");  // 读数据  printf("共享内存内容:%s\n", shm_ptr);  
    }  
    
5. 解除映射:shmdt
  • 头文件:#include <sys/types.h>#include <sys/shm.h>
  • 原型:int shmdt(const void *shmaddr);
  • 作用:断开共享内存与进程虚拟地址空间的映射(不销毁共享内存,仅解除当前进程的关联)。
  • 参数:shmaddrshmat 返回的内存首地址。
  • 返回值:
    • 成功:返回 0
    • 失败:返回 -1(检查 errno,如地址无效)。
6. 销毁共享内存:shmctl
  • 头文件:#include <sys/types.h>#include <sys/shm.h>
  • 原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 作用:控制共享内存(如销毁、查询状态)。
  • 参数:
    • shmid:共享内存 ID。
    • cmd:操作指令(IPC_RMID 表示标记销毁,需所有进程解除映射后实际释放)。
    • buf:填 NULL(销毁时无需额外参数)。
  • 返回值:
    • 成功:返回 0
    • 失败:返回 -1(检查 errno,如权限不足)。

(三)命令行工具

  • 查看 IPC 资源ipcs -a(查看共享内存、信号量、消息队列等)。
  • 删除共享内存
    • ipcrm -m shmid:通过 ID 删除(如 ipcrm -m 1234)。
    • ipcrm -M shmkey:通过 ftok 生成的 key 删除(如 ipcrm -M 0x12345678)。
http://www.dtcms.com/a/339855.html

相关文章:

  • C++实现教务管理系统,文件操作账户密码登录(附源码)
  • gitlab、jenkins等应用集成ldap
  • AI学习之DeepSeek本地化部署
  • 数据结构-栈和队列
  • Go语言并发编程 ----- sync包
  • Js逆向案例 Scrape Spa2(Webpack自吐)
  • 2020年EAAI SCI1区TOP,基于ORPFOA算法的多无人机在线变化任务路径规划,深度解析+性能实测
  • RAG 面试题(实时更新补充)
  • 基于SpringBoot的篮球馆预约管理系统【2026最新】
  • 西门子博途DB数据块的详细用法以及如何与威纶通触摸屏变量关联
  • 中兴B862AV3.2M/B862AV3.1-M2 晨星mso9385_安卓9_原厂备份救砖包
  • 机械原理的齿轮怎么学?
  • 【网络运维】Playbook部署文件:Files模块库&JINJA2模板
  • 根据Wireshark捕获数据包时间和长度绘制电脑发射信号波形
  • 图论——Bellman-Ford和SPFA
  • 《AI 与人类创造力:是替代者还是 “超级协作者”?》​
  • 切换Font Awesome 7 后图标变形解决
  • C++编程学习(第25天)
  • 1A AMOLED显示屏电源芯片BCT1838
  • UE5多人MOBA+GAS 50、英雄选择(一)
  • 福彩双色球第2025095期综合分析
  • 宿主获取插件View流程原理 - fetchViewByLayoutName
  • 国密算法及应用场景概述(SM1、SM2、SM3、SM4、SM7、SM9、祖冲之ZUC算法)
  • 大模型参数如何影响模型的学习和优化?
  • TheB.AI
  • C++常见面试题-3.C++11 及后续特性
  • 图像融合指标的代码
  • package.json详细字段解释
  • 基于 RxJava 构建强大的 Android 文件下载管理器
  • APM32芯得 EP.29 | 基于APM32F103的USB键盘与虚拟串口复合设备配置详解