一 共享内存原理
共享内存允许两个或多个进程共享给定的存储区域。 共享内存的特点:
1. 共享内存是进程间共享数据的一种最快的方法。一个进程向共享内存区域写数据,共享这块内存的所有进程就可以立刻看到这个数据;
2. 使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。若一个进程正在向共享内存写数据,则在他做完这步操作前,别的进程不应该去读、写这些数据;
3. 共享内存是系统级别的行为。
共享存储区的最小字节数:1
共享存储区的最大字节数:32M
共享存储区的最大个数:4096
每个进程能最多映射的共享存储区个数:4096
二 共享内存相关API
2.1 获得一个共享存储标识符shmget
- 需要的头文件和函数原型
int shmget(key_t key, size_t size, int shmflg);
-
功能 创建或打开一块共享内存区 -
参数
key:IPC键值
size:该共享内存大小(字节)
shmflg:标识函数行为及共享内存的权限
IPC_CREAT:如果不存在就创建
IPC_EXCL:如果已经存在则返回失败
位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式和open函数mode_t一样,但可执行权限未使用
- 返回值
成功:返回共享内存标识符
失败:返回-1
2.2 使用shell命令操作共享内存
- 查看共享内存ipcs -m
- 删除共享内存ipcrm -m shmid
2.3 建立进程的虚拟内存和物理内存的映射函数shmat
- 需要的头文件和函数原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
-
功能 将一个共享内存段映射到调用进程的数据段中 -
参数
shmid:共享内存标识符
shmaddr:共享内存映射地址(若为NULL则由系统指定)
shmflg:共享内存段的访问权限和映射提交
0:共享内存具有可读可写权限
SHM_RDONLY:只读
SHM_RND:(shmaddr非空时才有效)没有指定SHM_RND则此段连接到shmaddr所指定的地址上(shmaddr必须页对齐)。指定了SHM_RND则此段连接到shmaddr-shmaddr%SHMLBA所表示的地址上
- 返回值
成功:返回共享内存段映射地址
失败:-1
- 注意
shmat函数使用的时候第二个和第三个参数一般为NULL和0,即系统自动指定共享内存地址,并且共享内存可读可写
2.4 解除共享映射区
- 需要的头文件和函数原型
int shmdt(const void *shmaddr);
-
功能 将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存) -
参数
shmaddr:共享内存映射地址
- 返回值
成功:0
失败:-1
2.5 共享内存控制
- 需要头文件和函数原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- 功能
共享内存空间的控制 - 参数
shmid:共享内存标识符
cmd:函数功能控制
IPC_RMID:删除
IPC_SET:设置shmid_ds参数
IPC_STAT:保存shmid_ds参数
SHM_LOCK:锁定共享内存段(超级用户)
注意:SHM_LOCK用于锁定内存,禁止内存交换。并不代表共享内存锁定后禁止其他进程访问。其真正意义是:被锁定的内存不允许被交换到虚拟内存中。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能
SHM_UNLOCK:解锁共享内存段
buf:shmid_ds数据类型的地址,用来存放或修改共享内存的属性
- 返回值
成功:0
失败:-1
三 实例
int main(int argc, char * kwargs[])
{
//获取唯一key
key_t key = ftok("/",2222);
//获取共享内存的标识符(分配物理内存)
int shm_id = shmget(key, 32, IPC_CREAT|0666);;
//将虚拟内存和物理内存建立映射
char *buf = (char *)shmat(shm_id, NULL, 0);
//操作虚拟内存
strcpy(buf, "0123456789012345");
//printf("%s\n",buf);
//断开映射
shmdt(buf);
return 0;
}
|