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

Linux相关概念和易错知识点(52)(基于System V的信号量和消息队列)

目录

  • 1、System V信号量
    • (1)信号量的本质与核心原理
    • (2)PV原语(均为原子操作)
      • a. P原语(申请资源)
      • b. V原语(归还资源)
    • (3)System V信号量接口
      • a. 创建信号量集 semget
      • b. 控制信号量 semctl
      • c. PV操作 semop
    • (4)信号量管理
  • 2、System V 消息队列
    • (1)消息队列特点
    • (2)消息队列接口函数
      • a. 创建 / 获取消息队列 msgget
      • b. 消息队列控制 msgctl
      • c. 发送消息 msgsnd
      • d. 接收消息 msgrcv
    • (3)命令行管理

之前我分享过基于System V的共享内存的使用,上篇文章也引入mmap分析了其底层实现,即共享映射文件缓冲区使得不同进程看到同一块区域,本篇文章会继续分享System V标准下的信号量和消息队列。整体难度不大,不需记忆接口,了解即可,因此本文借助AI生成,仅做简单记录和介绍。

1、System V信号量

(1)信号量的本质与核心原理

无论是POSIX还是System V标准下,信号量本质是一个计数器,即资源的预定机制,主要用于进程间同步与互斥管理,在用环形队列实现生产者消费者模型中有很大用处。

信号量操作分为P操作(申请资源)与V操作(归还资源)。

信号量计数器s的含义:

  • s > 0:表示当前可用资源的个数
  • s = 0:表示无可用资源,且无等待进程
  • s < 0:表示无可用资源,|s|为等待队列中进程的个数

内核中信号量可由结构体表示:

structsemaphore{intvalue;structPCB*queue;};

(2)PV原语(均为原子操作)

a. P原语(申请资源)

  1. 执行 value–
  2. 判断 value < 0:若成立,说明资源不足
  3. 将当前进程加入等待队列并阻塞
  4. 进程调度切换,等待被唤醒
voidP(structsemaphore*sem){sem->value--;if(sem->value<0){add_to_queue(sem->queue,current_process);block_current_process();}}

b. V原语(归还资源)

  1. 执行 value++
  2. 判断 value <= 0:若成立,说明有进程在等待
  3. 从等待队列唤醒一个进程至就绪态
  4. 唤醒后的进程可重新尝试申请信号量
voidV(structsemaphore*sem){sem->value++;if(sem->value<=0){structPCB*proc=remove_from_queue(sem->queue);wake_up_process(proc);}}

(3)System V信号量接口

a. 创建信号量集 semget

intsemget(key_t key,intnsems,intsemflg);
  • key:唯一标识,与共享内存规则一致
  • nsems:信号量集中信号量的个数
  • semflg:支持 IPC_CREAT 与 IPC_EXCL
  • 返回值:成功返回 semid,失败返回 -1

b. 控制信号量 semctl

intsemctl(intsemid,intsemnum,intcmd,...);
  • semid:信号量集标识符
  • semnum:信号量下标,从0开始
  • cmd:
    • SETVAL:初始化单个信号量,该操作不具备原子性
    • IPC_RMID:删除整个信号量集,第二个参数无意义
  • 返回值:失败返回 -1

c. PV操作 semop

intsemop(intsemid,structsembuf*sops,size_t nsops);
  • sops:操作结构体数组
  • nsops:数组长度
  • 可同时对多个信号量执行原子操作,例如一个P、一个V
  • 返回值:成功 0,失败 -1

(4)信号量管理

  • 查看信号量:ipcs -s
  • 删除信号量:ipcrm -s

System V 信号量生命周期随内核,进程退出不会自动释放,必须手动删除,通常在析构函数中完成释放逻辑。

2、System V 消息队列

(1)消息队列特点

a.允许任意进程间通信
消息队列是内核提供的 System V IPC 机制,不要求进程之间存在亲缘关系,只要多个进程通过同一个 key 访问同一个消息队列,即可实现数据收发,支持无关联进程间通信。

b.消息自带类型标识,可按类型选择性接收
每条消息必须以一个 long 类型的消息类型字段开头,接收方可以指定只接收某一类型的消息,不匹配类型的消息会继续保留在队列中,也可以不指定类型直接读取最早消息,实现消息分类与分发。

c.支持全双工通信
通信双方可以使用不同消息类型分别进行发送和接收,无需切换读写方向,双向通信互不干扰,天然实现全双工。

d.生命周期随内核
消息队列创建后会持续存在于内核中,进程退出不会自动删除,只有通过调用msgctl(IPC_RMID) 或系统重启才会销毁。

e.面向数据块传输
以消息为单位传输,每条消息独立,不同于管道的字节流传输,边界清晰。

(2)消息队列接口函数

a. 创建 / 获取消息队列 msgget

intmsgget(key_t key,intmsgflg);
  • key:消息队列的唯一标识符,可通过 ftok 生成或手动指定
  • msgflg:权限位 + 创建标志
    • IPC_CREAT:队列不存在则创建,存在则返回已存在队列 ID
    • IPC_EXCL:与 IPC_CREAT 配合使用,队列已存在则报错,确保新建队列
    • 例:IPC_CREAT | 0666
  • 返回值:成功返回消息队列 ID msqid,失败返回 -1

b. 消息队列控制 msgctl

intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);
  • cmd:
    • IPC_RMID:删除消息队列,此时 buf 传 NULL
    • IPC_STAT:获取队列属性信息,存入 buf
    • IPC_SET:设置队列属性
  • 常用于删除队列:msgctl(msqid, IPC_RMID, NULL);

c. 发送消息 msgsnd

intmsgsnd(intmsqid,constvoid*msgp,size_t msgsz,intmsgflg);
  • msgp:指向自定义消息结构体指针,结构体必须以 long mtype 开头
  • msgsz:消息数据部分长度,不包含 mtype 字段
  • msgflg:一般为 0(阻塞发送),或 IPC_NOWAIT(非阻塞)
  • 消息结构体示例:
structmsgbuf{longmtype;charmtext[1024];};

d. 接收消息 msgrcv

intmsgrcv(intmsqid,void*msgp,size_t msgsz,longmsgtyp,intmsgflg);
  • msgtyp:要接收的消息类型
    • 0:接收队列中第一条任意类型消息
    • 0:接收指定类型的第一条消息

    • <0:接收类型 ≤ |msgtyp| 的最小类型消息
  • msgsz:数据缓冲区大小
  • msgflg:一般为 0(阻塞),或 IPC_NOWAIT、MSG_NOERROR 等

(3)命令行管理

  • 查看消息队列:ipcs -q
  • 删除消息队列:ipcrm -q msqid
http://www.jsqmd.com/news/615655/

相关文章:

  • F-Theta扫描透镜的性能评估
  • 2026年垃圾中转站设备优质推荐榜:移动垃圾压缩站、竖直直压式垃圾站、压缩垃圾中转站、地埋式垃圾压缩站、垂直式垃圾压缩站选择指南 - 优质品牌商家
  • [AI/向量数据库/GUI] Attu : Milvus 的图形化与一体化管理工具勇
  • 如何实现一个可插入自定义标签的文本输入框
  • 从零构建可审计、可回滚、可监控的向量检索服务:EF Core 10架构设计图+DDD分层实践(含GitHub可运行Demo)
  • 2026档案室密集柜推荐榜:档案室用密集柜/档案智能密集柜/橱式密集柜/电动密集柜/电动密集档案柜/移动档案密集柜/选择指南 - 优质品牌商家
  • OpenClaw插件开发:为Qwen3-14b_int4_awq添加钉钉通道支持
  • 电容是什么?一个“快充快放”的微型充电宝坷
  • 毕业设计实战:基于SSM+MySQL的社区医疗服务预约管理系统设计与实现指南
  • 别再踩坑了!SQL Server数据类型那点事儿,看懂这篇少背三个锅竟
  • 嵌入式系统开发:硬件思维与架构实践
  • 一个进程是 host root vs docker root
  • Linux I/O 演进史:从管道到零拷贝,一篇串起个服务端核心原语纠
  • OpenClaw技能组合策略:Qwen3-32B在复杂工作流中的模块化调用
  • 金融PHP支付配置终极Checklist(2024Q3央行金融科技新规适配版):58项必检条目,漏1项即触发监管通报
  • 绵阳高新区小学晚托自习
  • A Gift from the Integration of Discriminative andDiffusion-based Generative Learning: BoundaryRefi
  • OpenClaw配置备份指南:gemma-3-12b-it环境快速迁移与恢复
  • 嵌入式文件传输协议选型与优化实践
  • OpenClaw备份恢复方案:Qwen3-32B任务历史与技能配置迁移
  • OpenClaw代码审查:Qwen3.5-9B自动化质量检查
  • 2026武汉高评价日常保洁TOP10推荐:武汉物业保洁公司/武汉企业保洁公司/武汉保洁公司/武汉保洁外包公司/武汉保洁托管公司/选择指南 - 优质品牌商家
  • 嵌入式通信协议的状态机接收模块设计与优化
  • 2026年可靠熔体流动速率仪TOP推荐:简支梁冲击试验机/落锤冲击试验机/制样机/差热/差示扫描量热仪/开闭孔率测定仪/选择指南 - 优质品牌商家
  • SpringCloud-Stream + RocketMQ/Kafka
  • Boodskap数字孪生Arduino客户端库深度解析
  • 【Java】通过Mybatis Plus自带的方式,实现公共字段自动填充。
  • Google 修改账户归属地
  • AI编程实战:从零到一搭建全栈项目胺
  • 国内半导体展哪家好?盘点2026年实力半导体展为企业搭建桥梁 - 品牌2026