Linux :进程间通信(IPC)与信号

一、信号

1. 基本概念

信号是用于通知进程某个事件发生的软中断机制,是进程间异步通信的一种方式。

2. 核心信号与操作

  • SIGINT :由ctrl+c触发,默认功能是终止进程。
    • SIG_IGN:忽略该信号;
    • SIG_DFL:恢复信号的默认行为;
    • signal(信号值, 处理行为):修改信号的处理逻辑,实现信号功能替换。
  • kill():用于向进程发送指定信号,主动触发信号机制。

二、进程间通信(IPC)方式

进程间通信核心方式包括:管道、共享内存、消息队列、信号量、套接字,以下重点整理前四类核心机制。

1. 管道

管道是基于文件描述符的半双工通信方式,数据传输遵循先进先出(FIFO),分为有名管道和无名管道两类。

特性 有名管道 无名管道
名称 有文件名,存在于文件系统 无名称,仅通过文件描述符访问
进程关系 任意有权限的进程 仅亲缘进程(父子 / 兄弟)
生命周期 随文件系统(需手动删除) 随进程销毁而销毁
创建方式 mkfifo 命令 pipe() 系统调用
1.1 通用特性与注意事项
  • 通信模式:半双工(同一时刻仅能单向传输);
  • 数据特性:字节流无边界,若按消息传输需自定义格式(长度 + 数据),避免多读 / 少读;
  • 核心问题:
    1. 管道破裂:读端关闭后写端仍写入,触发SIGPIPE信号终止写端进程;
    2. 缓冲区阻塞:读空 / 写满会阻塞进程,需通过fcntl()设置非阻塞属性;
    3. 资源泄漏:进程退出前未关闭描述符,会导致缓冲区数据丢失。
1.2 测试与使用
  • 命令行测试:
    • 读端持续监听:while true;do cat < 管道文件;done
    • 写端写入:cat > 管道文件
  • 代码操作:
    • 读管道:使用read()函数,注意第三个参数不能用初始化的strlen
    • 写管道:使用write()函数向管道文件写入数据。

2. 共享内存

共享内存是最快的 IPC 方式,通过将同一块内存映射到多个进程的地址空间,实现数据直接共享。

2.1 核心函数
函数 功能 关键参数 / 返回值
shmget() 创建 / 获取共享内存 key:唯一标识;size:内存大小(新建填正数,获取填 0);shmflgIPC_CREAT(创建)+ 权限位;返回值:成功返回标识符,失败返回 - 1
shmat() 将共享内存映射到进程地址空间 shm_idshmget返回值;shm_addr:NULL(系统自动分配地址)/ 自定义地址;shmflg:0(读写)/SHM_RDONLY(只读);返回值:映射后的内存地址
2.2 操作流程
  1. 创建共享内存:shmget(key, size, IPC_CREAT | 0666)
  2. 映射到进程:shmat(shm_id, NULL, 0)
  3. 进程读写共享内存数据;
  4. 解除映射(可选):shmdt()
  5. 删除共享内存(释放资源):通过shmctl()设置IPC_RMID
2.3 练习场景
  • 读进程:持续读取共享内存中的数值;
  • 写进程:持续向共享内存写入数值。

3. 信号量

信号量用于进程间同步与互斥,本质是受保护的整数计数器,通过原子操作修改值,控制共享资源的访问。

3.1 核心概念
  • 原子操作:信号量的加减操作不可中断,避免多进程并发修改导致数据不一致;
  • 堵塞机制:信号量值为 0 时,获取该信号量的进程阻塞,直到其他进程释放资源;
  • 类型:
    • 二值信号量:值为 0/1,实现互斥(类似锁,一次仅一个进程访问);
    • 计数信号量:值为非负数,控制多个相同资源的并发访问;
  • P/V 原语:
    • P 操作(减 1):结果≥0 则进程继续,否则阻塞;
    • V 操作(加 1):永远不阻塞,若有阻塞进程则唤醒一个;
  • 临界资源:同一时刻仅允许一个进程访问的资源;
  • 临界区:访问临界资源的代码段。
3.2 核心函数
函数 功能 关键参数 / 返回值
semget() 创建 / 获取信号量集 key:唯一标识;nsems:信号量个数(新建 / 获取均需 > 0);semflgIPC_CREAT+ 权限;返回值:成功返回标识符,失败返回 - 1
semctl() 控制信号量集(设置 / 获取 / 删除) semid:信号量集标识符;semnum:信号量索引(整体操作忽略);cmdSETVAL(设初始值)/GETVAL(取值)/IPC_RMID(删除);可变参数:union semun(自定义联合体)
semop() 执行信号量 P/V 操作 semid:信号量集标识符;sops:指向sembuf结构体的指针(含sem_num(索引)、sem_op(±1)、sem_flgSEM_UNDO));nsops:操作数个数
3.3 关键结构体 / 联合体
  • 联合体semun(自定义):

    复制代码
    union semun {
        int val; // 用于SETVAL(设置信号量值)
        struct semid_ds *buf; // 用于IPC_STAT/IPC_SET(状态信息)
        unsigned short *array; // 用于GETALL/SETALL(批量操作)
        struct seminfo *_buf; // 用于IPC_INFO(系统限制)
    };
  • 结构体sembuf

    复制代码
    struct sembuf {
        unsigned short sem_num; // 信号量索引
        short sem_op; // 操作类型(+1/V操作,-1/P操作)
        short sem_flg; // 标志位,常用SEM_UNDO(异常退出时撤销修改)
    };
3.4 操作流程
  1. 创建信号量集:semget(key, nsems, IPC_CREAT | 0600)
  2. 设置信号量初始值:semctl(semid, 0, SETVAL, {.val = 1})(二值信号量);
  3. 执行 P/V 操作:通过semop()传入sembuf结构体(如sem_op = -1为 P 操作,sem_op = +1为 V 操作);
  4. 释放资源:semctl(semid, 0, IPC_RMID)(删除信号量集)。

三、补充工具

  • ipcs:查看系统中 IPC 资源(共享内存、信号量、消息队列);
  • ipcrm:手动删除 IPC 资源(配合ipcs结果清理)。
相关推荐
Lfei51201 小时前
Centos 9 stream部署zabbix7.0.25(最新)
linux·运维·centos
枫叶落雨2222 小时前
服务器下载两个jdk
linux·运维·服务器
Elivs.Xiang2 小时前
基于docker安装MySQL、RabbitMQ、ElasticSearch、minio
linux·mysql·elasticsearch·docker·rabbitmq
Jason_zhao_MR2 小时前
基于米尔RK3576核心板的国产割草机器人解决方案
大数据·linux·人工智能·单片机·物联网·机器人·嵌入式
相思难忘成疾2 小时前
Linux SSH免密登录实验:基于Xshell的公钥认证机制
linux·运维·ssh·rhce
其实防守也摸鱼5 小时前
GDB安装与配置(保姆级教程)【Linux、Windows系统】
linux·运维·windows·命令模式·工具·虚拟机·调试
AC赳赳老秦11 小时前
OpenClaw二次开发实战:编写专属办公自动化技能,适配个性化需求
linux·javascript·人工智能·python·django·测试用例·openclaw
mounter62512 小时前
【内核新动向】告别物理槽位束缚:深度解析 Linux Virtual Swap Space 机制
linux·内存管理·kernel·swap·virtual swap
handler0112 小时前
从零实现自动化构建:Linux Makefile 完全指南
linux·c++·笔记·学习·自动化