System V IPC – 共享内存
共享内存故名思意,一段可以被共享的内存区域,两个及以上的进程都可以使用该区域进行数据的交互,进程使用该内存的时候需要将该内存附加到本进程的地址空间中,当需要发送数据的时候,只需要将数据复制到共享内存中即可,当需要读取数据时,同样复制出来即可。
这种IPC机制无需内核介入,相比于管道、消息队列收发数据时,需要进行用户空间与内核空间进行数据拷贝的方式来说,共享内存这种IPC技术速度更快(虽然每个进程也存在通过系统调用来执行复制操作的开销)
由于共享内存的这种特性,应该知道共享内存是可以同时被多个进程所访问的,那么必然会存在多个进程访问临界资源的风险,所以需要互斥的使用共享内存。(下一篇博客将会介绍信号量实现对资源的互斥访问)
system的三种高级IPC的某些操作都非常的类似,故本篇不在重复相同的特性,最详细的特性参考https://blog.csdn.net/weixin_48617416/article/details/120449215
-
共享内存的创建
int shmget(key_t key, size_t size, int shmflg); //参数2:创建的共享内存大小 //其它与前面介绍的msgque类似,后续相同的不再说明,初学者建议阅读完我上一篇介绍的消息队列的博客再来学习共享内存比较好
创建好之后同样可以通过ipcs来查看,或者ipcrm -m/M来删除
-
使用共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg); //参数2:如果填NULL,表示让该内存段会被附加到内核选择一块合适的地址上,这是最常用的做法 //成功返回附加共享内存段的地址,失败返回(void*)-1,并且置错误码
-
解除依附
int shmdt(const void *shmaddr); //参数:附加共享内存段的地址,shmat的返回值
-
代码示例:
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h> #include <sys/types.h> int main(int argc, char **argv) { //创建大小为1024的共享内存 int shmid = shmget(128, 1024, IPC_CREAT|0664); if (0 != fork()) { //将共享内存附加到本进程的地址上 char *p = (char *)shmat(shmid, NULL, 0); //向共享内存里写如数据 strcpy(p, "woshishuju"); wait(NULL); //解除依附 shmdt(p); } else { char *p = (char *)shmat(shmid, NULL, 0); //取数据 char buf[64] = {0}; strcpy(buf, p); printf("buf = %s\n", buf); shmdt(p); exit(0); } return 0; } 执行结果: buf = woshishuju
-
共享内存的控制操作
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
一个共享内存段是可以被锁在内存中的,这样该共享内存段就不会被交换出内存了,这样可以带来性能上的提升。具体实现可以使用shmctl函数实现(Linux系统所特有的操作):
- 将参数cmd填写成SHM_LOCK宏,将共享内存锁进内存
- 将参数cmd填写成SHM_UNLOCK宏,则是解锁操作,表示允许它被交换出去
(ps:如果想要给内存加锁还可以使用
mlock()
函数) -
代码示例
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h> #include <sys/types.h> int main(int argc, char **argv) { //创建大小为1024的共享内存 int shmid = shmget(128, 1024, IPC_CREAT|0664); //锁内存 shmctl(shmid, SHM_LOCK, 0); return 0; } //运行 [wy@wy ~/textCode/text/ipc/sem]$ ./shmctl [wy@wy ~/textCode/text/ipc/sem]$ ipcs -m ------------ 共享内存段 -------------- 键 shmid 拥有者 权限 字节 连接数 状态 0x00000080 65536 wy 664 1024 0 已锁定
通过命令可以看到共享内存的状态变成了锁定
-
可以通过ipcs命令查看共享内存的一些限制
[wy@wy ~/textCode/text/ipc/sem]$ ipcs -lm ---------- 同享内存限制 ------------ 最大段数 = 4096 最大段大小 (千字节) = 18014398509465599 最大总共享内存 (千字节) = 18014398509481980 最小段大小 (字节) = 1
-
以上就是共享内存的使用简介,下一篇信号量!
能力有限,如有错误望各位大佬不吝指正,原创不易,转载请注明出处