本文共 2403 字,大约阅读时间需要 8 分钟。
共享内存的实现简单来说就是一个物理内存被映射到多个进程的地址空间。映射该共享内存的进程可以直接内存存取对数据进行修改访问,从而实现不同进程之间的数据通信。这种方式的优势在于实现简单且效率高,不需要数据拷贝。
shmget用于创建或获取一块共享内存,返回共享内存的标识shmid。
int shmget(key_t key, size_t size, int shmflg)
常用权限:
返回值:成功返回非负整数shmid,失败返回-1。
将共享内存映射到进程的地址空间,共享内存的attach数加一。
void *shmat(int shmid, const void *shmaddr, int shmflg)
返回值:成功返回指针,指向共享内存第一个字节,失败返回-1。
将共享内存与当前进程脱离,attach数减一。
int shmdt(const void *shmaddr)
返回值:成功返回0,失败返回-1。
用于控制共享内存。
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
常用命令:shmctl(shmid, IPC_RMID, NULL)用于删除共享内存。
如果多个进程使用同一共享内存,其中一个进程执行删除操作(shmctl shmid IPC_RMID NULL),该共享内存被标记为dest。只有当所有进程解除对共享内存的连接(attach为0)后,共享内存才会真正删除。
如果共享内存标记为dest后,再次使用相同key值创建共享内存,会创建新的共享内存段,无法与原有共享内存通信。
如果不使用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;}
在两个进程之间测试共享内存的读写功能,设置权限为0666,共享内存大小为1024字节,连接数为2,当前用户为xd。
在一个进程中执行删除操作,发现其他进程仍可继续使用共享内存,除非退出连接。
通过以上实践,我们掌握了如何在C语言中使用共享内存实现进程间通信。通过测试验证了共享内存的创建、读写和删除流程,理解了共享内存的工作原理和使用注意事项。
转载地址:http://qhue.baihongyu.com/