Linux 之 【进程间通信】(共享内存、ftok、shmget、shmat、shmdt、shctl、IPC相关指令)
目录1.共享内存的通信原理2.共享内存的创建ftokshmgetIPC相关命令共享内存的生命周期3.共享内存的去关联shmatshmdt4.共享内存的释放shmctlshmctl(shmid, IPC_RMID, NULL);5.共享内存的使用1.共享内存的通信原理操作系统预先分配一块物理内存称为共享内存多个进程通过各自的页表将这段内存映射到自身的虚拟地址空间通常是共享区使得不同进程的虚拟地址最终指向同一块物理内存。进程可以直接读写该内存区域进行数据交换从而实现高效通信但需配合同步机制保证数据一致性由于进程具有严格的独立性其直接分配的内存只能自己独享无法直接用于进程间通信。为了解决这一矛盾共享内存必须由作为全局管理者的操作系统内核来提供。进程通过系统调用请求操作系统执行以下核心步骤来间接使用共享内存创建/获取一块共享内存区域、将其关联映射到自身地址空间并使用、通信完成后去关联、最终由系统销毁该区域。创建/获取申请内存进程请求操作系统创建一块新的共享内存或获取一块已存在的共享内存的标识符。操作系统在物理内存中为其分配空间。关联进程将这块共享内存映射到自己的进程地址空间通常是共享区操作系统建立进程页表到该物理内存的映射关系并返回映射后的虚拟首地址供进程访问。使用进程通过得到的虚拟地址直接读写该内存区域进行进程间通信。去关联通信完成后进程断开与该共享内存的映射关系去关联使其从本进程的地址空间中移除。销毁释放当所有使用该共享内存的进程都完成去关联后操作系统最终释放该共享内存资源。为了管理系统中可能存在的多块共享内存操作系统采用“先描述再组织”的方式用一个内核数据结构如struct shmid_ds来描述每一块共享内存的信息大小、权限、关联进程数等再通过链表等数据结构将这些描述对象组织起来实现统一高效的管理2.共享内存的创建ftok组成部分名称与类型详细说明与作用函数原型key_t ftok(const char *pathname, int proj_id);将文件路径和项目ID转换为System V IPC机制消息队列、共享内存、信号量使用的键值(key)。函数功能生成IPC键值根据给定的路径名和项目ID生成一个唯一的key_t类型的键值用于不同进程通过相同参数获取同一个IPC对象。包含头文件#include sys/ipc.h#include sys/types.h使用ftok函数必须包含这两个头文件。参数1const char *pathname路径名指向一个已存在且可访问的文件或目录的路径字符串。•必须存在路径指向的文件必须存在且有访问权限。•通常用法使用一个固定的、所有进程都能访问的文件如/tmp/myapp,/etc/passwd, 或项目特定文件。•原理依据函数会使用该文件的st_dev设备号和st_inoi-node号信息。参数2int proj_id项目ID用户指定的单字节整数值0-255。•范围限制只有低8位有效0-255超出范围会被截断取低8位。•用途允许在同一文件上生成多个不同的key值。•常见值通常用ASCII字符表示如a、b或十六进制0x01等。返回值key_t key成功返回生成的key_t类型的键值通常是32位整数。失败返回(key_t)-1并设置errno指示错误原因•ENOENT路径名指向的文件不存在•EACCES对路径名指向的文件无搜索权限•ESTALE文件系统已卸载关键特性1.确定性相同(pathname, proj_id)组合在任何进程、任何时间调用都产生相同的key值。2.跨进程性不同进程使用相同参数即可获得相同key从而访问同一个IPC对象。3.非唯一性风险如果文件被删除重建i-node号可能变化导致key值改变。常见错误1.文件不存在最常见错误确保路径文件存在且稳定。2.权限不足进程对路径文件无访问权限。3.项目ID溢出超出255的值会被截断可能导致意外冲突。4.文件被删除重建i-node号改变新旧进程可能获得不同key。共享内存的键值key是用户进程预先约定的一个标识符它的核心作用是让不同进程能够通过相同的key值找到或创建同一个共享内存对象。key并非由操作系统保证全局唯一而是由应用程序自身确保其唯一性通常通过ftok()函数基于文件路径生成。第一个进程使用shmget(key, size, IPC_CREAT)创建共享内存时系统会将此key与它关联起来后续其他进程只需使用相同的key调用shmget()即可获取该共享内存的访问句柄。因此key在整个共享内存通信机制中扮演的是进程间“约定地址”的角色类似于文件系统中的路径名其唯一性和一致性由使用它的各进程共同维护操作系统无法预知哪些进程需要通信、何时通信。若由系统自动分配key则进程仍需通过其他渠道如文件、环境变量或硬编码交换这个key这反而增加了耦合度和复杂性。用户约定key通常通过ftok或预定义常量使得通信双方能以松耦合的方式独立连接到同一资源共享内存因此成为一种独立、通用、不依赖特定进程关系的通信机制shmget组成部分名称与类型详细说明与作用功能获取共享内存标识符根据key创建或获取一块共享内存返回一个内核标识符(shmid)用于后续操作shmat,shmdt,shmctl。参数1key_t key键值用于唯一标识系统中共享内存对象。•IPC_PRIVATE(0)总是创建新的共享内存通常用于父子进程间。•用户指定key通过ftok()函数生成或直接指定一个非零整数用于无亲缘关系进程间的约定。参数2size_t size请求的共享内存大小字节。•创建时指定新共享内存的最小尺寸系统可能会向上取整到页大小如4KB的整数倍。•获取时如果只是获取已存在的共享内存size可以为0若指定了大小且小于已存在内存的大小可能会报错。参数3int shmflg创建标志与权限标志的组合。这是一个位掩码由两部分按位或(|)组成A. 行为控制标志•IPC_CREAT如果key对应的共享内存不存在则创建它。如果存在则直接获取其shmid。•IPC_EXCL与IPC_CREAT一同使用。如果共享内存已存在则调用失败返回-1errno设为EEXIST。这用于确保创建者拿到的是全新的内存。B. 权限标志八进制• 例如0666表示所有用户属主、组员、其他人都可读写。• 例如0644属主可读写组员和其他人只读。• 权限位实际受系统umask值影响最终权限 shmflg ~umask。返回值int shmid成功返回一个非负整数即共享内存标识符。这是后续所有操作挂接、控制、去关联的句柄。失败返回-1并设置全局变量errno指示错误原因如ENOENT-未找到,EACCES-权限不足,EEXIST-已存在,EINVAL-参数无效等。申请共享内存时操作系统会直接按内存页通常4KB的整数倍进行物理内存分配然后让用户使用申请的那一部分这样设计较为简单。所以建议申请4kb的整数倍减少浪费在共享内存通信机制中IPC键值key是用户层进程间约定的查找标识符它由应用程序通过预定义或ftok函数生成用于在不同进程中指向同一个共享内存对象共享内存标识符shmid是操作系统内核分配和管理共享内存的唯一标识它在系统范围内唯一进程通过shmget系统调用获得shmid后所有后续操作映射、控制、分离都基于此shmid进行。shmid与“一切皆文件”的理念兼容性较差因为它是一个独立的整数句柄而不是通过文件系统路径访问key像是一个逻辑路径名但其实现机制独立于文件系统。IPC相关命令# 查看所有IPC资源 ipcs # 查看特定类型的资源 ipcs -m # 共享内存 ipcs -q # 消息队列 ipcs -s # 信号量 # 详细查看 ipcs -a # 所有详细信息默认 ipcs -l # 显示系统限制 ipcs -p # 显示PID信息 ipcs -t # 显示时间信息 ipcs -c # 显示创建者/拥有者 ipcs -u # 显示摘要使用情况# 删除共享内存 ipcrm -m shmid # 按shmid删除 ipcrm -M key # 按key删除 # 删除消息队列 ipcrm -q msqid # 按msqid删除 ipcrm -Q key # 按key删除 # 删除信号量 ipcrm -s semid # 按semid删除 ipcrm -S key # 按key删除 # 删除所有用户拥有的IPC资源危险 ipcrm -a # 删除当前用户的所有IPC ipcrm -A # 删除所有用户的IPC需要root共享内存的生命周期共享内存的生命周期是随内核的用户不主动关闭共享内存会一直存在除非内核重启用户释放3.共享内存的去关联shmat项目详细说明函数原型void *shmat(int shmid, const void *shmaddr, int shmflg)功能描述将共享内存段关联到调用进程的地址空间使进程能够访问共享内存包含头文件#include sys/types.h#include sys/shm.h参数1int shmid•由shmget()返回的共享内存标识符• 必须是已存在的有效共享内存ID• 用于指定要附加的共享内存段参数2const void *shmaddr• 期望的附加地址建议设为NULL•shmaddr NULL系统自动选择合适地址•shmaddr ! NULL尝试在指定地址附加需对齐• 通常设置为NULL让系统选择可避免地址冲突参数3int shmflg• 附加标志位按位或组合•SHM_RDONLY以只读方式关联•SHM_RND当shmaddr非NULL时将其向下取整到SHMLBA边界•0默认读写方式返回值成功返回关联后的共享内存段在共享区的起始地址void*类型失败返回(void*)-1并设置errno权限控制• 创建时通过shmget()的权限位控制如0666• 关联时可通过SHM_RDONLY限制为只读• 权限检查进程必须有相应的访问权限引用计数每次成功shmat()会增加shm_nattch计数每次shmdt()会减少计数当计数为0且已标记删除时内存被释放错误码EACCES权限不足EINVALshmid无效或shmaddr不对齐ENOMEM进程地址空间不足EMFILE进程附加的共享内存段过多ENOSPC超出系统限制注意事项1. 关联后必须检查返回值是否为(void*)-12. 不同进程关联后在各自共享区的起始地址可能不同不应存储绝对指针3. 使用完毕后必须调用shmdt()分离4. 确保同步机制信号量等已就绪5. 考虑使用SHM_RDONLY提高安全性shmdt项目详细说明函数原型int shmdt(const void *shmaddr)功能描述将共享内存段从调用进程的地址空间中分离解除关联包含头文件#include sys/types.h#include sys/shm.h参数const void *shmaddr• 由shmat()返回的共享内存起始地址• 必须是有效的、已关联的共享内存地址• 不能是NULL或无效地址返回值成功返回0失败返回-1并设置errno引用计数变化shm_nattch--减少关联进程计数当计数为0且shm_perm.mode包含IPC_RMID标志时物理内存被释放错误码EINVALshmaddr不是已关联的共享内存地址**EFAULT**shmaddr指向无效地址罕见 |与shmat关系配对操作shmat- 关联建立映射shmdt- 分离解除映射注意事项1. 分离后不能再使用该指针访问共享内存2. 分离不释放物理内存除非是最后一个进程且已标记删除3. 可以多次调用shmdt对同一地址多次调用返回EINVAL4. 指针变量本身不会被修改但指向的内存已无效进程退出进程正常或异常退出时系统自动执行shmdt操作但显式调用shmdt是良好编程习惯分离后的指针指针变量仍保留原值但指向无效内存建议分离后立即设为NULLshmdt(ptr); ptr NULL;4.共享内存的释放shmctl项目详细说明函数原型int shmctl(int shmid, int cmd, struct shmid_ds *buf)功能描述对共享内存段进行控制操作包括查询状态、修改属性、删除等包含头文件#include sys/ipc.h#include sys/shm.h参数1int shmid• 共享内存标识符• 由shmget()返回的有效ID参数2int cmd• 控制命令指定要执行的操作• 主要分为三类查询、设置、控制参数3struct shmid_ds *buf• 数据缓冲区指针• 根据cmd不同可能是输入或输出• 某些cmd可设为NULL返回值成功根据cmd不同返回不同值失败返回-1并设置errno命令分类查询命令IPC_STAT, IPC_INFO, SHM_INFO, SHM_STAT设置命令IPC_SET控制命令IPC_RMID, SHM_LOCK, SHM_UNLOCK命令值功能buf参数用途返回值权限要求IPC_STAT2获取共享内存状态信息输出缓冲区接收状态信息0读权限IPC_SET1修改共享内存参数输入缓冲区提供新参数0属主或rootIPC_RMID0立即/延迟删除共享内存可设为NULL0属主或rootIPC_INFO3获取系统IPC信息输出struct shminfo索引值无SHM_INFO14获取系统共享内存信息输出struct shm_info索引值无SHM_STAT13获取共享内存状态通过索引输出struct shmid_dsshmid无SHM_LOCK11锁定共享内存到物理RAM可设为NULL0rootSHM_UNLOCK12解锁共享内存可设为NULL0rootshmctl(shmid, IPC_RMID, NULL);标记删除立即将共享内存标记为dest状态延迟释放如果nattch 0立即释放物理内存和内核结构如果nattch 0等待所有进程shmdt()分离后自动释放阻止新挂接标记后其他进程无法再shmat()挂接该内存// IPC_RMID 的典型使用模式 int main() { int shmid shmget(key, size, IPC_CREAT|0666); // 立即标记删除推荐做法 shmctl(shmid, IPC_RMID, NULL); // 此时 // 1. 已关联的进程可继续使用 // 2. 新进程无法关联 // 3. 所有进程分离后自动释放 void *ptr shmat(shmid, NULL, 0); // ... 使用 ... shmdt(ptr); // 最后一个进程分离后内存释放 return 0; }5.共享内存的使用processa.cc#include comm.hpp //读取 int main() { //创建与关联 int shmid CreateShm(); char* shmaddr (char*)shmat(shmid, nullptr, 0); //创建管道 Init init; // 打开管道 int fd open(FIFO_FILE, O_RDONLY); if (fd 0) { logObj(Fatal, error string: %s, error code: %d, strerror(errno), errno); exit(FIFO_OPEN_ERR); } //开始通信 struct shmid_ds shmds; char tmp; while(true) { int n read(fd, tmp, 1);//看看是否被通知 if(n 0) break; cout client say shmaddr endl; sleep(1); shmctl(shmid, IPC_STAT, shmds); cout shm nattch: shmds.shm_nattch endl; cout shm size: shmds.shm_segsz endl; printf(shm key: 0x%x\n, shmds.shm_perm.__key); cout shm mode: shmds.shm_perm.mode endl; } //去关联与删除 shmdt(shmaddr); shmctl(shmid, IPC_RMID, nullptr); close(fd); return 0; }processb.cc#include comm.hpp //写入 int main() { //获取与关联 int shmid GetShm(); char* shmaddr (char*)shmat(shmid, nullptr, 0); // 打开管道 int fd open(FIFO_FILE, O_WRONLY); if (fd 0) { logObj(Fatal, error string: %s, error code: %d, strerror(errno), errno); exit(FIFO_OPEN_ERR); } //开始通信 while(true) { cout Please Enter; fgets(shmaddr, 4096, stdin); write(fd, c, 1);//通知对方 } //去关联 shmdt(shmaddr); return 0; }1processa是读端processb是写端2processa创建并关联共享内存后进行读取操作processb获取并关联共享内存后进行写入操作3进程一旦拥有并关联共享内存后进程就能够直接将共享内存作为自己的内存空间来使用不需要通过系统调用。所以一旦processb进行写入操作processa立马就能执行读取操作4显然使用共享内存进行通信是所有进程间通信方式中最快的因为它拷贝少通信方式数据拷贝次数内核/用户切换具体过程共享内存1次或0次1次建立映射1. 数据写入共享内存1次2. 其他进程直接读取0次拷贝管道4次2次读写各1次1. 用户缓冲区→内核管道缓冲区1次2. 内核→用户缓冲区1次总计2次拷贝/方向双向4次5当然共享内存的数据要由用户自己维护这是因为共享内存没有同步读端不会阻塞等待写端写入和互斥写端未完整写入完数据就被读端读取导致数据不一致问题机制6这里使用命名管道进行保护措施同步机制写端先通过共享内存进行完写入操作后再通过命名管道发送一个字符通知读端读端只有通过命名管道读取到字符后才通过共享内存进行读取操作

相关新闻

Linux 之 【进程间通信】(消息队列与信号量、Systrm VIPC在内核中数据结构设计)

Linux 之 【进程间通信】(消息队列与信号量、Systrm VIPC在内核中数据结构设计)

目录 1.消息队列 2.Systrm V IPC在内核中数据结构设计 3.临界资源与临界区 4.信号量 1.消息队列 操作系统在内核空间创建并维护多个消息队列作为共享资源,每个队列都有唯一的标识符。不同进程通过相同的标识符访问同一个队列,从而实现进程间通信。进…

2026/7/7 11:17:58 阅读更多 →
如何提高大数据领域数据建模的准确性和可靠性

如何提高大数据领域数据建模的准确性和可靠性

如何提高大数据领域数据建模的准确性和可靠性 关键词:大数据建模、数据准确性、模型可靠性、特征工程、数据预处理、模型验证、分布式计算 摘要:本文深入探讨了在大数据环境下提高数据建模准确性和可靠性的关键技术和方法。文章从数据预处理、特征工程、模型选择和验证等多个…

2026/7/5 8:04:22 阅读更多 →
【Termux】Photopea离线版部署

【Termux】Photopea离线版部署

Photopea是捷克开发者Ivan Kutskir开发的免费浏览器端专业图像编辑器(2013年推出),界面与操作高度对标Photoshop,完全本地运行、无需上传文件、支持离线(PWA),同时提供付费去广告与可自行部署的…

2026/7/3 18:27:42 阅读更多 →

最新新闻

实战复现CitrixBleed 2漏洞:从内存越界读取到会话劫持

实战复现CitrixBleed 2漏洞:从内存越界读取到会话劫持

1. 项目概述:一次针对企业核心边界的实战化漏洞复现最近在梳理企业边界设备的安全风险时,我又一次把目光投向了Citrix NetScaler。作为全球范围内广泛应用的应用交付控制器(ADC)和网关设备,它承载着大量企业的关键业务…

2026/7/7 11:15:02 阅读更多 →
5分钟上手:Switch图形化注入工具TegraRcmGUI终极指南

5分钟上手:Switch图形化注入工具TegraRcmGUI终极指南

5分钟上手:Switch图形化注入工具TegraRcmGUI终极指南 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windows平台设计的Ni…

2026/7/7 11:13:01 阅读更多 →
品牌全案策划服务如何选择?2026年企业需关注的5个维度

品牌全案策划服务如何选择?2026年企业需关注的5个维度

品牌全案策划服务是企业建立系统性品牌体系的核心环节,需要从服务范围、团队专业度、数据能力、执行经验和成本结构五个维度综合评估。品牌全案策划服务是指为企业提供从品牌战略规划到视觉设计、营销推广、运营维护的一站式综合性服务。据QYResearch调研数据显示&a…

2026/7/7 11:13:01 阅读更多 →
从RSA到ML-KEM:密钥封装机制演进与后量子密码迁移实战

从RSA到ML-KEM:密钥封装机制演进与后量子密码迁移实战

1. 密钥封装机制:从信任基石到量子威胁下的重塑如果你在2024年之前配置过TLS证书,或者调试过SSH连接,那么“RSA密钥交换”这个概念对你来说一定不陌生。它就像互联网世界的“信任邮差”,几十年来默默无闻地保障着我们每一次网页浏…

2026/7/7 11:11:00 阅读更多 →
USVInland 数据集实战:基于 27 段序列的 SLAM 与水体分割算法评测

USVInland 数据集实战:基于 27 段序列的 SLAM 与水体分割算法评测

USVInland 数据集实战:基于 27 段序列的 SLAM 与水体分割算法评测水面无人驾驶技术正迎来前所未有的发展机遇,而高质量的数据集是推动算法进步的关键基石。USVInland 作为全球首个专注于内河航道场景的多传感器数据集,为研究者提供了丰富的真…

2026/7/7 11:11:00 阅读更多 →
数据库一体机简史:从ODA到zData X,命名之中的玄机

数据库一体机简史:从ODA到zData X,命名之中的玄机

在Exadata问世三年之后,Oracle公司于2011年9月在旧金山Oracle OpenWorld大会上正式发布了其数据库一体机的低端产品ODA(Oracle Database Appliance,如图1所示)。有意思的是,从命名上看,ODA才是真正意义上的…

2026/7/7 11:08:59 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻