总结一下共享内存的用法:
1.四个函数总的头文件:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
2.共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成
1)shmget函数:创建一个共享内存对象并返回共享内存标识符 (或得到一个共享内存标识符)
函数原型:int shmget(key_t key, size_t size, int shmflg)
第一个参数 key:参数key表示所要创建或打开的共享内存的键值。无论何时创建一个IPC对象(如调用shmget),都需要指定一个key,它的数据类型是key_t。这个key由内核转变为标识符.
- 0(IPC_PRIVATE):会建立新共享内存对象
- 大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值,(留个疑问)
第二个参数 size:代表共享内存的大小,一般用sizeof(数据结构)来指定
- 大于0的整数:新建的共享内存大小,以字节为单位
- 0:只获取共享内存时指定为0
第三个参数 shmflg : 用来设置shmget函数的操作类型,也可以用来设置共享内存的访问权限。两者可以通过逻辑或(“|”)来连接。其中第一个参数key和第三个参数shmflg共同决定了shmget的操作类型,具体如下:
- 如果key被设置为IPC_PRIVATE时,第三个参数shmflg无论取什么值,shmget都只用来创建一个新的共享内存区域。
- 如果key不是被设置为IPC_PRIVATE时,由key和shmflg共同决定shmget是创建还是打开共享内存区域。如函数调用shmget(key, size, IPC_CREAT)中,如果key为内核中某个已经存在的共享区域的键值,则执行打开操作。否则创建一个新的共享内存区域。
例如: key_t key = ftok("./", 12);
shmid = shmget(key, sizeof(int), IPC_CREAT | 0666);
函数返回值: 成功 返回 相应的共享内存标识符,失败返回-1
2)shmat函数:把共享内存区对象映射到调用进程的地址空间
void *shmat(int shm_id,const void *shm_addr,int shmflg);
第一个参数 : shmid 是上面产生的共享内存标识符
第二个参数 : shmaddr 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
第三个参数 : shmflg SHM_RDONLY:为只读模式,其他为读写模式,可以指定为0
函数返回值: 附加好的共享内存地址(成功) 错误 返回-1;
3)shmdt函数:当前进程分离共享内存
int shmdt(const void *shmaddr);
4)shmctl函数
和信号量的semctl函数类似,控制共享内存
int shmctl(int shm_id,int command,struct shmid_ds *buf);
shm_id:共享内存标识符
command: 有三个值
IPC_STAT:获取共享内存的状态,把共享内存的shmid_ds结构复制到buf中。
IPC_SET:设置共享内存的状态,把buf复制到共享内存的shmid_ds结构。
IPC_RMID:删除共享内存
buf:共享内存管理结构体。具体结构可参考定义。
3.共享内存需要注意的问题
共享内存没有同步机制,当多个进程同时向共享内存读写数据时,我们需要使用互斥锁,读写锁,信号量,条件变量等来确保数据的一致性