博客
关于我
System V共享内存的基本使用与实现
阅读量:330 次
发布时间:2019-03-04

本文共 2403 字,大约阅读时间需要 8 分钟。

共享内存实践

系统V共享内存

共享内存实现进程间通信

共享内存的实现简单来说就是一个物理内存被映射到多个进程的地址空间。映射该共享内存的进程可以直接内存存取对数据进行修改访问,从而实现不同进程之间的数据通信。这种方式的优势在于实现简单且效率高,不需要数据拷贝。

C语言共享内存实现

shmget函数

shmget用于创建或获取一块共享内存,返回共享内存的标识shmid。

int shmget(key_t key, size_t size, int shmflg)

  • key:键值,用于唯一标识共享内存段。
  • size:共享内存区块大小。
  • shmflg:创建时使用的标志位,第一位表示进制数,第二位表示当前用户权限,第三位表示用户组权限,第四位表示其他用户权限。

常用权限:

  • 0666:可读、可写、可执行。
  • 0644:可读、可写。

返回值:成功返回非负整数shmid,失败返回-1。

shmat函数

将共享内存映射到进程的地址空间,共享内存的attach数加一。

void *shmat(int shmid, const void *shmaddr, int shmflg)

  • shmid:共享内存标识。
  • shmaddr:指定连接地址,若为NULL则让内核自动选择合适地址。
  • shmflg:标志位,SHM_RND(取整对齐)或SHM_RDONLY(只读),其他为可读可写。

返回值:成功返回指针,指向共享内存第一个字节,失败返回-1。

shmdt函数

将共享内存与当前进程脱离,attach数减一。

int shmdt(const void *shmaddr)

返回值:成功返回0,失败返回-1。

shmctl函数

用于控制共享内存。

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

  • shmid:共享内存标识码。
  • cmd:操作指令,支持IPC_RMID等删除操作。
  • buf:保存共享内存模式状态和访问权限的结构体。

常用命令:shmctl(shmid, IPC_RMID, NULL)用于删除共享内存。

共享内存注意事项

shmctl删除共享内存

如果多个进程使用同一共享内存,其中一个进程执行删除操作(shmctl shmid IPC_RMID NULL),该共享内存被标记为dest。只有当所有进程解除对共享内存的连接(attach为0)后,共享内存才会真正删除。

key值创建的共享内存标记为dest后再次创建

如果共享内存标记为dest后,再次使用相同key值创建共享内存,会创建新的共享内存段,无法与原有共享内存通信。

不使用shmctl删除共享内存

如果不使用shmctl删除共享内存,即使连接数attach为0,共享内存仍然存在,下一次连接仍可使用。可以通过ipcs -m shmid统一删除共享内存。

共享内存实现

代码实现

为了测试共享内存功能,编写了一个简单的C语言程序:

#include 
#include
#include
#include
#include
#include
#define SHM_SIZE 1024int main() { int shmid = -1; int key = 10; int size = 1024; // 创建共享内存 shmid = shmget(key, size, IPC_CREAT | 0666); if (shmid < 0) { perror("shmget"); exit(1); } // 映射共享内存 char *ptr = NULL; ptr = shmat(shmid, NULL, 0); if (ptr == (void *) -1) { perror("shmat"); exit(1); } while (1) { char sym; printf("请输入r/w/d或e退出:\n"); scanf(" %c", &sym); if (sym == 'e') { break; } if (sym == 'r') { if (ptr[0] != '\0') { printf("共享内存内容:%s\n", ptr); } continue; } if (sym == 'w') { memset(ptr, 0, size); printf("请输入要写入的内容:"); char buf[1024]; scanf("%s", buf); memcpy(ptr, buf, strlen(buf)); continue; } if (sym == 'd') { if (shmctl(shmid, IPC_RMID, NULL) == -1) { perror("shmctl"); exit(1); } } if (sym != 'r' && sym != 'w' && sym != 'd') { printf("命令错误!\n"); continue; } } // 解除共享内存 if (shmdt(ptr) < 0) { perror("shmdt"); exit(1); } return 0;}

测试

测试1

在两个进程之间测试共享内存的读写功能,设置权限为0666,共享内存大小为1024字节,连接数为2,当前用户为xd。

测试2

在一个进程中执行删除操作,发现其他进程仍可继续使用共享内存,除非退出连接。

总结

通过以上实践,我们掌握了如何在C语言中使用共享内存实现进程间通信。通过测试验证了共享内存的创建、读写和删除流程,理解了共享内存的工作原理和使用注意事项。

转载地址:http://qhue.baihongyu.com/

你可能感兴趣的文章
C#开发BIMFACE系列35 服务端API之模型对比6:获取模型构建对比分类树
查看>>
C# 规范建议
查看>>
.NET 5.0正式发布,新功能特性(翻译)
查看>>
C语言+easyX图形库的推箱子实现
查看>>
反汇编-流程控制语句-2-循环控制语句分析
查看>>
调试vs2019代码的流程
查看>>
游戏外挂基础-概述
查看>>
脱壳与加壳-加壳-6-代码实现加密导入表
查看>>
Typora配置PicGo时,提示Failed to fetch
查看>>
ASP.NET Core 使用 URL Rewrite 中间件实现 HTTP 重定向到 HTTPS
查看>>
ASP.NET CORE MVC 实现减号分隔(Kebab case)样式的 URL
查看>>
SQL优化 MySQL版 -分析explain SQL执行计划与笛卡尔积
查看>>
bcolz的新操作
查看>>
Linux的s、t、i、a权限(转)
查看>>
zmq的send
查看>>
C++中的delete加深认识
查看>>
windows消息机制(转)
查看>>
STL笔试面试题总结(干货)(转)
查看>>
XML 和 HTML 之间的差异
查看>>
qt中moc的作用
查看>>