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

进程间通信:消息队列、信号量与内核管理

一、System V 消息队列消息队列 - OS维护了一个队列 - 通过队列的形式让不同进程之间看到同一份资源消息队列提供了一种一个进程给另一个进程发送有类型数据块的方式每个数据块都被认为是有一个类型接收者进程接收的数据块可以有不同的类型值OS需要对消息队列进行管理 -【先描述再组织】两个进程需要需要如何保证自己看到的是同一份资源 上层约定同一个keyIPC资源必须手动/代码删除否则不会自动清除除非重启System V IPC资源生命周期随内核1.1 理解消息队列管道和共享内存传输的都是无格式字节流就像你把一堆信扔进一个麻袋对方拿出来不知道哪封是先写的、哪封是重要的。消息队列则给每封信贴上了“类型标签”接收方可以按类型取信。特点数据有结构每条消息包含一个正整数的类型 任意字节的数据体。支持按类型接收进程可以只接收自己关心的消息。内核管理队列存在于内核中不随进程退出而消失除非手动删除或重启系统。1.2 核心数据结构与函数内核为每个消息队列维护一个msqid_ds结构里面记录了权限、时间戳、消息数量、字节数等。ftok—— 生成唯一 keykey_t ftok(const char *pathname, int proj_id);通过一个路径和项目ID生成一个几乎唯一的 key供msgget使用。️msgget—— 创建或获取消息队列int msgget(key_t key, int msgflg); // msgflg: IPC_CREAT | 0666 (不存在则创建权限 rw-rw-rw-)返回值消息队列标识符 msqidmsgsnd—— 发送消息int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); // msgp 指向一个结构体第一个成员必须是 long mtype struct msgbuf { long mtype; // 消息类型必须 0 char mtext[100]; // 消息数据可自定义大小 }; // msgsz 是 mtext 的字节数不含 mtypemsgrcv—— 接收消息ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); // msgtyp 0 : 取队列中第一条消息 // msgtyp 0 : 取类型等于 msgtyp 的第一条消息 // msgtyp 0 : 取类型小于等于 |msgtyp| 的最小类型的第一条消息️msgctl—— 控制消息队列int msgctl(int msqid, int cmd, struct msqid_ds *buf); // cmd: IPC_RMID 删除队列1.3 简单例子服务端与客户端comm.hpp公共头#pragma once #include sys/types.h #include sys/ipc.h #include sys/msg.h #include string.h #include iostream #include unistd.h #define PATHNAME /tmp #define PROJ_ID 0x66 #define CLIENT_TYPE 1 #define SERVER_TYPE 2 struct Message { long mtype; char mtext[256]; };server.cpp接收客户端消息#include comm.hpp int main() { key_t key ftok(PATHNAME, PROJ_ID); int msqid msgget(key, IPC_CREAT | 0666); if (msqid -1) { perror(msgget); exit(1); } Message msg; while (true) { // 接收类型为 CLIENT_TYPE 的消息 ssize_t s msgrcv(msqid, msg, sizeof(msg.mtext), CLIENT_TYPE, 0); if (s 0) { std::cout Server recv: msg.mtext std::endl; if (strcmp(msg.mtext, quit) 0) break; } } msgctl(msqid, IPC_RMID, nullptr); // 删除队列 return 0; }client.cpp发送消息#include comm.hpp int main() { key_t key ftok(PATHNAME, PROJ_ID); int msqid msgget(key, IPC_CREAT | 0666); // 获取已有队列 if (msqid -1) { perror(msgget); exit(1); } Message msg; msg.mtype CLIENT_TYPE; while (true) { std::cout Input: ; std::cin.getline(msg.mtext, sizeof(msg.mtext)); msgsnd(msqid, msg, strlen(msg.mtext) 1, 0); if (strcmp(msg.mtext, quit) 0) break; } return 0; }⚠️注意System V IPC 资源消息队列、共享内存、信号量的生命周期随内核如果不主动删除IPC_RMID即使所有进程退出它们依然存在直到系统重启。可以用ipcs -q查看ipcrm -q msqid删除。1.4 查看System V IPC二、信号量也称信号灯本质是一个计数器用来表明临界资源中资源的数量的多少信号量是 System V IPC 中最抽象但最核心的机制它不传递数据只负责解决多进程对共享资源的同步与互斥问题是实现进程间 “协作规则” 的关键。2.1 为什么需要信号量共享内存是最快的 IPC但它没有同步互斥机制。两个进程同时写同一块共享内存数据会乱掉 —— 这就是并发问题。2.2 核心概念概念通俗解释经典例子共享资源临界资源多个进程能同时访问的公共资源内存、文件、设备等多进程操作的同一块共享内存、同一个打印机临界区进程中访问共享资源的代码段进程中对共享内存写数据的那几行代码互斥任何时刻只允许一个进程进入临界区访问共享资源打印机同一时间只能给一个进程打印同步多个进程访问共享资源时必须按预定的顺序执行生产者进程生产数据后消费者进程才能读取不能反着来信号量本质上就是一个计数器记录当前还有多少个资源可用。进程访问资源前先“申请”P操作计数器减1用完“释放”V操作计数器加1。如果计数器为 0申请进程就会阻塞等待直到其他进程释放资源。核心原则对共享资源的保护本质是对访问共享资源的临界区代码的保护而非资源本身。2.3 理解信号量电影院买票的经典比喻放映厅有 100 个座位 → 信号量初值为 100。每个观众买票 → 信号量减 1预订一个座位。票卖光了信号量 0→ 后来的观众必须等待。观众离场 → 信号量加 1唤醒等待的人。买票就是“预订资源”而不是真的要坐上去的那一刻才占用。信号量的本质是内核维护的一个计数器结合P/V 原语操作原子操作不可被中断实现对临界区的进入控制。计数器的数值代表当前可用的共享资源数量P 操作申请资源计数器减 1若结果 0进程阻塞等待若≥0进程可进入临界区V 操作释放资源计数器加 1若结果≤0唤醒一个阻塞的等待进程。最经典的信号量二元信号量互斥锁当信号量的计数器只能取0 或 1时就是二元信号量对应我们常说的 “互斥锁”初始值为 1表示共享资源可用进程进入临界区前执行 P 操作计数器变为 0资源被占用进程退出临界区后执行 V 操作计数器变回 1资源释放若其他进程此时执行 P 操作计数器变为 - 1进程阻塞直到持有锁的进程执行 V 操作。通俗比喻信号量就像停车场的入口闸机计数器是停车场的剩余车位初始值为 1010 个车位每进一辆车P 操作车位减 1每出一辆车V 操作车位加 1车位为 0 时后续车辆进程只能排队等待阻塞直到有车开出V 操作。二元信号量就是只有 1 个车位的停车场同一时间只能停一辆车。2.4 二元信号量VS多元信号量原子操作P/V 操作是内核实现的原子操作不会被进程调度中断避免了多进程操作计数器时的竞态问题生命周期随内核与消息队列、共享内存一致进程退出后信号量不会自动释放需手动删除用于同步 / 互斥二元信号量实现互斥多元信号量计数器 1实现同步资源预订机制进程必须先通过 P 操作申请信号量才能访问共享资源本质是对共享资源的 “预订”避免冲突。2.5 信号量与共享内存的配合共享内存是最快的 IPC 方式但本身没有同步互斥机制多个进程同时读写会导致数据混乱比如一个进程写数据时另一个进程同时读得到残缺数据。因此实际开发中共享内存必然与信号量配合使用用信号量保护共享内存的临界区实现 “一人写多人读” 或 “一人读无人写” 的规则。通俗理解共享内存是一间公共书房共享资源信号量是书房的门钥匙二元信号量同一时间只有一个人能拿到钥匙进入书房临界区其他人只能在门口等待。2.6 相关函数semget—— 创建/获取信号量集int semget(key_t key, int nsems, int semflg); // nsems: 信号量集中信号量的个数一般写 1 // 返回值信号量集标识符 semidsemctl—— 控制信号量初始化、删除等int semctl(int semid, int semnum, int cmd, ...); // 初始化cmd SETVAL第四个参数是 union semun union semun { int val; struct semid_ds *buf; unsigned short *array; };// 删除cmd IPC_RMIDsemop—— P/V 操作int semop(int semid, struct sembuf *sops, size_t nsops); struct sembuf { unsigned short sem_num; // 信号量编号0 表示第一个 short sem_op; // 1 是 V操作释放-1 是 P操作申请 short sem_flg; // 一般 0阻塞或 IPC_NOWAIT };创建、初始化分离semget() 创建信号量只分配资源semctl() 初始化值SETVAL设置初始三、内核是组织管理IPC资源所有 System V IPC 资源消息队列、共享内存、信号量都有三个共同属性内核通过这三个属性实现统一管理键值key_tIPC 资源的 “全局唯一标识”由ftok函数生成用于进程间查找对应的 IPC 资源标识idIPC 资源的 “内核局部标识”由shmget/msgget/semget返回进程通过 id 操作具体的 IPC 资源权限结构kern_ipc_perm所有 IPC 资源的公共属性结构体包含资源的所有者uid/gid、创建者cuid/cgid、访问权限mode、键值key等是内核管理 IPC 资源的基础。3.1 三种 IPC 资源的统一抽象关键理解shmid,msgid,semid本质上都是数组下标它们不是指针不是句柄而是ipc_id_ary数组的索引通过下标找到kern_ipc_perm *再强制类型转换成具体结构3.2 用 C 实现多态Polymorphism// 1. 基类所有 IPC 资源共有的权限信息 struct kern_ipc_perm { key_t key; // IPC键值 uid_t uid; // 所有者 gid_t gid; // ... 其他权限字段 }; // 2. 柔性数组技巧结构体内部带数组 struct ipc_id_ary { int size; // 数组大小 struct kern_ipc_perm *p[0]; // 柔性数组 }; // 3. 具体 IPC 资源结构以消息队列为例 struct msg_queue { struct kern_ipc_perm q_perm; // 放在第一个兼容基类 long q_stime; // 发送时间 long q_rtime; // 接收时间 struct list_head q_messages; // 消息链表 // ... 其他特有字段 }; struct sem_array { struct kern_ipc_perm sem_perm; // 同样放在第一个 struct sem *sem_base; // 信号量数组 int sem_nsems; // ... }; struct shmid_kernel { struct kern_ipc_perm shm_perm; // 同样放在第一个 struct file *shm_file; // 共享内存文件 int id; // ... };所有结构体以相同字段开头强制类型转换实现继承3.3 什么是柔性数组// 传统固定数组浪费空间或不够 struct fixed { int cnt; char buffer[100]; // 固定100字节可能浪费或不够 }; // 柔性数组运行时决定大小 struct flexible { int cnt; char buffer[0]; // 或 char buffer[]; (C99标准) // 不占空间只是一个标记 };char buffer[0];不占空间只是一个标记IPC 用柔性数组节省内存不需要指针间接跳转数组和结构体在一起缓存友好访问p[i]时数组数据在附近命中率高动态扩容可以realloc重新分配更大的空间总结对比IPC 类型主要作用是否传输数据同步机制生命周期典型函数消息队列有类型的数据块是自带类型随内核msgget/msgsnd/msgrcv共享内存最快的数据交换是需额外锁随内核shmget/shmat/shmdt信号量同步与互斥否原子 P/V随内核semget/semop/semctl匿名管道亲缘进程流式数据是自动同步随进程pipe命名管道任意进程流式数据是自动同步随文件系统mkfifo/open/read/write

相关文章:

进程间通信:消息队列、信号量与内核管理

一、System V 消息队列消息队列 -> OS维护了一个队列 -> 通过队列的形式,让不同进程之间看到同一份资源消息队列,提供了一种,一个进程给另一个进程发送有类型数据块的方式!每个数据块都被认为是有一个类型,接收者…...

LightOnOCR-2-1B实战体验:上传图片,秒出文字,简单高效

LightOnOCR-2-1B实战体验:上传图片,秒出文字,简单高效 1. 从“想法”到“文字”,只需要三步 你有没有过这样的经历?手机拍了一张会议白板的照片,想把上面的要点整理成文档,结果对着照片一个字…...

初创公司 0 代码上线 App:UXbot 全流程实战

非技术背景的初创公司创始人,可以使用 UXbot 这款 AI 无代码应用构建工具,在无需设计师和工程师介入的情况下,独立完成从产品需求描述到 Android APK 真机安装的完整链路。整个过程分为 5 个步骤,核心耗时约半天,输出物…...

如何高效配置无人机电子调速器:专业级ESC配置工具实战指南

如何高效配置无人机电子调速器:专业级ESC配置工具实战指南 【免费下载链接】esc-configurator A Web-App to flash your BLHeli_S and AM32 based ESCs from the browser using the Web-Serial API. 项目地址: https://gitcode.com/gh_mirrors/es/esc-configurato…...

3个秘诀让黑苹果EFI配置效率提升100倍:告别拆机与代码的烦恼

3个秘诀让黑苹果EFI配置效率提升100倍:告别拆机与代码的烦恼 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 当你对着教程里满屏的ACPI补丁…...

深度揭秘ControlNet-v1-1 FP16模型:5大实战技巧突破SD1.5显存瓶颈

深度揭秘ControlNet-v1-1 FP16模型:5大实战技巧突破SD1.5显存瓶颈 【免费下载链接】ControlNet-v1-1_fp16_safetensors 项目地址: https://ai.gitcode.com/hf_mirrors/comfyanonymous/ControlNet-v1-1_fp16_safetensors ControlNet-v1-1_fp16_safetensors作…...

【C++初阶】手撕C++ string类

🎬 博主名称:键盘敲碎了雾霭 🔥 个人专栏: 《C语言》《数据结构》 《C》 ⛺️指尖敲代码,雾霭皆可破 文章目录 一、前言:为什么要手写string类?二、整体架构设计2.1 成员变量设计2.2 类结构总览 三、核心构…...

实战指南:基于快马AI构建可部署的z-library全栈应用

实战指南:基于快马AI构建可部署的z-library全栈应用 最近在尝试搭建一个电子图书馆应用,类似z-library的功能。这个项目涉及用户系统、支付、推荐等多个模块,对于个人开发者来说确实有点复杂。不过我发现使用InsCode(快马)平台可以大大简化开…...

用快马ai快速原型一个永久在线crm网站,验证你的产品思路

最近在验证一个CRM产品的市场可行性,需要快速搭建一个能永久在线的基础原型。传统开发流程从环境搭建到功能实现至少需要一周,而通过InsCode(快马)平台的AI辅助,我用不到半天就完成了核心功能验证。以下是具体实践过程: 明确最小可…...

全栈实战:在快马平台从零到一开发一个可部署的极客日报应用

今天想和大家分享一个最近在InsCode(快马)平台上完成的实战项目——极客日报全栈应用开发。这个项目从零开始,完整实现了前后端分离的Web应用开发流程,特别适合想系统性学习全栈开发的同学参考。 项目架构设计 整个应用采用经典的三层架构:前…...

ai开发ai:借助快马平台智能体辅助完成openclaw千问模型的深度配置与优化

最近在折腾OpenClaw配置千问模型的项目,发现整个过程特别适合用AI来辅助开发。这种"用AI开发AI应用"的循环特别有意思,今天就来分享下我的实践心得。 核心配置脚本的AI协作开发 配置OpenClaw最头疼的就是那些复杂的错误处理逻辑。我直接在In…...

【单片机】STM32晶振引脚不连晶振时的做法

STM32不使用外部晶振时,OSC_IN和 OSC_OUT接法:1、对于100脚或者144脚的产品,OSC_IN应接地,OSC_OUT应悬空;2、对于少于100脚的产品,有两种接法:OSC_IN和OSC_OUT分别通过10K电阻接地,此方法可提高…...

大模型领域岗位梯队详解:小白程序员转型宝典,速收藏![特殊字符]

大模型领域岗位梯队详解:小白程序员转型宝典,速收藏!🔥 本文详细解析了大模型领域的岗位梯队,从底层架构到应用开发,涵盖了预训练、基础设施、模型优化、后训练、多模态等多个方向。文章强调了当前大模型领…...

收藏 | RAG核心认知:从“检索+生成”到“实时智能”,小白也能秒懂大模型技术范式!

收藏 | RAG核心认知:从“检索生成”到“实时智能”,小白也能秒懂大模型技术范式! RAG(检索增强生成)通过动态联动外部知识库与大语言模型(LLM),构建“实时信息输入-精准内容输出”闭…...

收藏必备!小白程序员轻松入门大模型,解锁医学AI新技能

收藏必备!小白程序员轻松入门大模型,解锁医学AI新技能 大语言模型在医疗健康领域应用初见成效,但存在知识体系固化的局限。本文介绍了检索增强生成(RAG)技术,该技术模拟医生查阅最新文献的工作逻辑&#xf…...

零基础也能入行!大模型AI学习指南,收藏这份进阶路线图

零基础也能入行!大模型AI学习指南,收藏这份进阶路线图 本文为AI大模型新手提供了一份系统化学习路线图,从认知重塑、基础准备、核心知识入门、动手实践到定位方向与求职准备,详细拆解了学习步骤与关键点。强调先应用后理论、重实践…...

大模型应用落地:新手/程序员必备五类关键技术选型指南(收藏版)

大模型应用落地:新手/程序员必备五类关键技术选型指南(收藏版) 本文从产品经理视角出发,详细介绍了大模型应用落地的五类关键技术(Prompt、RAG、Workflow、Agent、模型微调)及其适用场景。强调技术选型应遵…...

Nano Banana Pro图像生成与编辑技术解析

介绍 Nano Banana Pro 不久前,发布了Nano Banana(Gemini 2.5 Flash图像模型)。从修复旧照片到生成微型模型,Nano Banana在图像编辑领域迈出了一大步,让普通创作者能够表达自己的创造力。今天,推出Nano Bana…...

DeepSeek 架构深度解析:从原理到实践的完整指南

引言:重新定义大模型效率的国产之光2024年12月,DeepSeek-V3的技术报告正式发布,迅速在AI社区引发轰动。这款拥有671B总参数的混合专家模型,以仅557万美元的训练成本——不到GPT-4传闻训练成本的1/10——实现了与GPT-4o和Claude-3.…...

Locust模拟真实用户并发及优化建议

第一部分:为什么要压测?因为生产环境不会跟你商量 你可以把API想象成一家餐厅的后厨。本地跑通,就像你一个人在后厨炒菜,流水线得很顺。但突然来了一百个客人同时点餐,后厨就乱套了——锅不够、灶不够、配菜来不及切。…...

收藏!小白/程序员轻松入门大模型,抓住AI风口高薪就业机会!

收藏!小白/程序员轻松入门大模型,抓住AI风口高薪就业机会! 本文详细介绍了AI大模型领域的热门就业岗位,包括AI模型研发工程师、数据科学家、算法工程师、AI应用开发工程师、AI平台架构师、AI产品经理和AI测试工程师等。文章强调了…...

2026年木蜡油定做厂家大盘点,究竟哪家才是行业首选?

在当今注重环保和品质的时代,木蜡油作为一种天然环保的涂料,受到了越来越多消费者的青睐。无论是室内外木器家具、木艺制品,还是全屋定制、装饰装修等领域,木蜡油都有着广泛的应用。然而,市场上木蜡油定做厂家众多&…...

Zenith.NET v0.0.7:Metal 后端落地,.NET GPU 抽象的跨平台旅程

为什么要做 Zenith.NET?.NET 生态有不少图形相关的库——绑定层如 Silk.NET、Vortice,抽象层如 Veldrid、Evergine。但现有的抽象层要么停留在较旧的 API 版本(如 DX11/OpenGL),要么是商业引擎的一部分,难以…...

路径构建引擎:开源角色养成系统的架构解析与实践指南

路径构建引擎:开源角色养成系统的架构解析与实践指南 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding 一、价值定位:构建虚拟角色的数字孪生平台 …...

Wand-Enhancer完整指南:如何安全增强WeMod用户体验的终极方案

Wand-Enhancer完整指南:如何安全增强WeMod用户体验的终极方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer Wand-Enhancer是一款专为WeMod…...

高效批量获取抖音无水印视频:从概念到实战的完整指南

高效批量获取抖音无水印视频:从概念到实战的完整指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppor…...

开源广告拦截工具AdGuard浏览器扩展:全平台部署与效率优化指南

开源广告拦截工具AdGuard浏览器扩展:全平台部署与效率优化指南 【免费下载链接】AdguardBrowserExtension AdGuard browser extension 项目地址: https://gitcode.com/gh_mirrors/ad/AdguardBrowserExtension 【价值解析】AdGuard扩展如何重塑你的网络浏览体…...

2026年一体化HR系统TOP8盘点:从集团管控到AI落地的选型指南

进入2026年,企业选一体化HR系统不再只看模块是否齐全,更看能否支撑集团管控、复杂用工、数据洞察与AI提效闭环。红海云在国央企与复杂场景的深度适配、以及AI在招聘与员工服务等环节的可落地性上更突出;用友、北森、金蝶在业人融合、PaaS扩展…...

Dress Code高分辨率虚拟试衣数据集:计算机视觉时尚研究的终极实战指南

Dress Code高分辨率虚拟试衣数据集:计算机视觉时尚研究的终极实战指南 【免费下载链接】dress-code 项目地址: https://gitcode.com/gh_mirrors/dre/dress-code Dress Code是由意大利摩德纳大学研究团队开发的高分辨率多类别虚拟试衣数据集,为计…...

BiliTools AI视频总结功能:革新B站内容消费体验的智能解决方案

BiliTools AI视频总结功能:革新B站内容消费体验的智能解决方案 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTool…...