赞
踩
共享内存(Shared Memory)就是允许两个或多个进程访问同一个内存空间,是在多进程通信的最高效的方式。
操作系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们自己的地址空间中,如果某个进程修改了共享内存中的数据,其它的进程读到的数据也将会改变。由于共享内存会成为进程用户空间的一部分,所有这种通信方式不需要内核介入。
共享内存并未提供锁机制,也就是说,在某一个进程对共享内存的进行读写的时候,不会阻止其它的进程对它的读写,可能会出现数据的错乱。
1、必备头文件
#include <sys/ipc.h>
#include <sys/shm.h>
2、shmget()
获取或创建共享内存
// 获取或者创建共享内存
int shmget(key_t key, size_t size, int shmflg);
- key是共享内存的键值,是一个整数,是共享内存在系统中的编号,不同共享内存的编号不同。一般使用十六进制。
- size表示待创建共享内存的大小,以字节为单位
- shmflg表示共享内存的访问权限,与文件的权限一样,
0666 | IPC_CREAT 表示全部用户对它可读写
- 返回值:返回共享内存标识
3、shmat()
把共享内存连接到当前进程的地址空间
void *shmat(int shm_id, const void *shm_addr, int shmflg);
- shm_id表示由 shmget函数返回的 共享内存的标识号
- shm_addr指定共享内存连接到当前进程中的地址位置,通常为 NULL,表示让系统来选择共享内存的地址。
- shm_flg是一组标志位,通常为0
- 返回值:
调用成功:返回一个指向共享内存第一个字节的指针
调用失败:返回 -1
4、shmdt()
将共享内存从当前进程中分离,相当于 shmat()
函数的反操作
int shmdt(const void *shmaddr);
- shmaddr是 shmat函数 返回的地址
- 返回值:
调用成功:返回 0
调用失败:返回 -1
5、shmctl()
删除共享内存
int shmctl(int shm_id, int command, struct shmid_ds *buf);
- shm_id是共享内存的标识号
- command 填写 IPC_RMID
- buf 填写 0
- 返回值:
调用成功:返回 0
调用失败:返回 -1
shmget()
函数创建一个新共享内存段或取得一个现有的共享内存段的标识号。返回后续可调用的需要用到的共享内存标识符。shmat()
函数附上共享内存段,即让该共享内存段成为调用进程的虚拟内存中的一部分(进程绑定共享内存段)shmat()
返回的内存地址指针,就可以在程序中对该共享内存段进行操作(写操作/读操作)。shmdt()
函数,让进程和共享内存段分离,进程无法再操作共享内存了。(只是分离,共享内存依然存在)shmctl()
函数,删除共享内存段,只有当与该共享内存段绑定好的进程都分离后,才会销毁,只有一个进程需要执行这一步。// write_shm.c #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> int main() { int shmid; // 共享内存标识符 // 创建共享内存,键值为0x5005,共1024字节。 if ( (shmid = shmget((key_t)0x5005, 1024, 0666 | IPC_CREAT)) == -1) { printf("shmat(0x5005) failed\n"); return -1; } char *ptext = NULL; // 用于指向共享内存的指针 // 将共享内存连接到当前进程的地址空间,由ptext指针指向它 ptext = (char *)shmat(shmid, NULL, 0); // 操作本程序的ptext指针,就是操作共享内存 char *str = "Hello world!"; memcpy(ptext, str, strlen(str)); // 把共享内存从当前进程中分离 shmdt(ptext); return 0; }
// read_shm.c int main() { int shmid; // 共享内存标识符 // 创建共享内存,键值为0x5005,共1024字节。 if ( (shmid = shmget((key_t)0x5005, 1024, 0666 | IPC_CREAT)) == -1) { printf("shmat(0x5005) failed\n"); return -1; } char *ptext = NULL; // 用于指向共享内存的指针 // 将共享内存连接到当前进程的地址空间,由ptext指针指向它 ptext = (char *)shmat(shmid, NULL, 0); // 操作本程序的ptext指针,就是操作共享内存 printf("%s\n", ptext); // 把共享内存从当前进程中分离 shmdt(ptext); // 删除共享内存 if (shmctl(shmid, IPC_RMID, 0) == -1) { printf("shmctl(0x5005) failed\n"); return -1; } }
read_shm.c
的输出结果:
Hello world!
可以看出,write_shm.c
申请共享内存,并写入数据,read_shm
获取共享内存标识号,并绑定进程,读取该共享内存中的数据。
ipcs -m # 查看现有的所有共享内存段
ipcrm -m shmid # 根据共享内存段的标识号,删除共享内存
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。