
Linux:进程间通信——共享内存
read.c运行结果:
发布日期:2021-05-07 02:16:06
浏览次数:24
分类:精选文章
本文共 3164 字,大约阅读时间需要 10 分钟。
Linux:进程间通信——共享内存
原理
共享内存的原理是:在物理内存中开辟一段空间,这段物理内存的空间可以被不同的进程附加到自己的共享区中,附加的进程再通过操作共享区来实现数据的交换。
共享内存的创建
知道共享内存的原理以后,接下来我们要关心的问题是怎样创建一个共享内存,Linux中可以用shmget函数来创建共享内存。
函数原型:#includeint shmget(key_t key,size_t size,int shmflg);参数解释: key:共享内存标识符,这个标识符相当于共享内存的身份证;程序员在第一次创建的时候,可以随意给值,只要和当前操作系统当中的其他的共享内存标识符不重复 size:共享内存的大小,单位字节 shmflag: IPC_CREAT:如果共享内存不存在,则创建IPC_EXCL: 需要搭配IPC_CREAT一起使用,使用按位或 例子:IPC_CREAT|IPC_EXCL:如果想要获取的共享内存已经存在,则报错,如果想要获取的共享内存是刚刚创建出来的,则返回操作句柄 返回值:返回共享内存的操作句柄
代码:
#include#include #include #define KEY 0X99999999 int main() { int shmid = shmget(KEY,1024,IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } else { printf("creat success!\n"); } while(1) { sleep(1); } return 0; }
创建完成之后用ipcs -m命令查看

键 | shmid | 拥有者 | 权限 | 字节 | nattch | 状态 |
---|---|---|---|---|---|---|
0x99999999 | 32768 | dev | 664 | 1024 | 0 |
其中shimid表示共享内存操作句柄,nattch表示的是附加的进程数目
将共享内存附加到进程
创建了共享内存之后我们需要做的就是把共享内存附加到进程了,可以使用shmat函数来实现
函数原型:#includevoid *shmat(int shmid,const void *shmaddr,int shmflg);参数说明: shmid:操作句柄 shmaddr:附加到共享内存的什么虚拟地址,允许传递NULL值,让操作系统帮我们选择附加到共享内存的那个地址,这个地址通过该函数的返回值返回给我们 shmflg: SHM_RDONLY:规定当前进程只能对共享内存进程读操作 0:可读可写 返回值:返回共享内存附加到共享内存的地址
代码:
shared.c#include#include #include #include #define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); strcpy((char*)lp, "hello world!\n"); while(1) { sleep(1); } return 0;}
read.c
#include#include #include #include #define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); printf("%s\n", (char*)lp); return 0;}
shared.c运行结果:


将共享内存和进程分离
函数原型:int shmdt(const void *shmaddr);参数解释: shmaddr:shmat的返回值
shared.c
#include#include #include #include #define KEY 0x89898989int main(){ int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if(shmid < 0) { perror("shmget"); return -1; } void* lp = shmat(shmid, NULL, 0); strcpy((char*)lp, "hello world!\n"); while(1) { sleep(1); } return 0;}
还是上面的程序,当我们把分离函数加上去以后,就分离了一个进程,nattch的值就会-1。
操作共享内存
函数原型:Int shmctl(int shmid,int cmd.struct shmid_ds *buf);参数说明: shmid:共享内存操作句柄 cmd:告诉shmctl函数需要什么操作 IPC_STAT:获取当前共享内存的属性信息,放在buf中,buf是出参 IPC_SET:设置共享内存的属性信息,是用buf来进行设置的,buf是出参 IPC_RMID:删除共享内存,buf可以直接传递NULL buf:共享内存结构体
使用这个函数也可以删除共享内存,当我们使用这个函数或者ipcrm删除共享内存后我们会发现:
(1)当使用shmctl或者ipcrm删除共享内存之后,共享内存实际上已经被释放了 (2)共享内存释放掉之后,共享内存的标识符就会被设置成为0X00000000,表示其他进程不能通过之前的标识符找到该共享内存,并且内存的状态也会被设置成dest(如果共享内存已经被释放了,但是还有进程附加着共享内存,当前描述共享内存的结构体并没有被释放,只有当前共享内存的附加进程数量为0的时候才会被释放) 释放后键 | shmid | 拥有者 | 权限 | 字节 | nattch | 状态 |
---|---|---|---|---|---|---|
0x00000000 | 32768 | dev | 664 | 1024 | 0 | dest |
其中shimid表示共享内存操作句柄,nattch表示的是附加的进程数目
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月21日 19时05分13秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
大白话说Java反射:入门、使用、原理
2019-03-06
集合系列 Set(八):TreeSet
2019-03-06
JVM基础系列第11讲:JVM参数之堆栈空间配置
2019-03-06
MySQL用户管理:添加用户、授权、删除用户
2019-03-06
比技术还重要的事
2019-03-06
linux线程调度策略
2019-03-06
软中断和实时性
2019-03-06
Linux探测工具BCC(可观测性)
2019-03-06
Opentelemetry Metrics SDK
2019-03-06
流量控制--2.传统的流量控制元素
2019-03-06
SNMP介绍及使用,超有用,建议收藏!
2019-03-06
SDUT2161:Simple Game(NIM博弈+巴什博弈)
2019-03-06
51nod 1596 搬货物(二进制处理)
2019-03-06
来自星星的祝福(容斥+排列组合)
2019-03-06
Hmz 的女装(递推)
2019-03-06
HDU5589:Tree(莫队+01字典树)
2019-03-06
不停机替换线上代码? 你没听错,Arthas它能做到
2019-03-06
sharding-jdbc 分库分表的 4种分片策略,还蛮简单的
2019-03-06
分库分表的 9种分布式主键ID 生成方案,挺全乎的
2019-03-06