共享内存
共享内存是三个IPC机制中的一个。它允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在进行
的进程之
间
传递
数据
的
一种非常有效的
方式。
大多数的共享内存的实现,
都把
由不同进程之间共享的内存安排为
同一段物理内存.
具体过
程我来
画一张
图帮
助大家更好的理解.
首先大家都应该知道我们每一个程序其实看到的内存都是虚拟内存,他需要进行页表的映射将进程地址映射到物理内存
当中.
共享内存的大致原理相信我们已经看明白了,就是让两个进程地址通过页表映射到同一片物理地址以便于通信, 当
你可以给一
个
区
域里面写入数据,理所当然你就可以从中拿取数据,这也就构成了进程间的双向通信,而且共享内存是
IPC通信当中传输
速度
最快的
通信方式没有之一,这里的原因你想一下,那种操作会有直接从内存里取出放入数据简单?
还有它的生命周期随
内核.
说了这么都共
享内存的好,是时候损一波它了,
共享内存并未提供同步机制,也就
是说,在第一个进程结束对共享内存
的
写操
作之
前,并无自动
机制可以阻止第二个进程开始对它
进行读取。所以我们通常需要用其
他的机制来同步对共享内
存的
访问,例
如
前面说
到的信号量。
LINUX下共享内存相关命令:
由于共享内存的生命周期随内核,所以当我们不适用它的时候,最好的方式还是让它入土为安,删掉它.
查看共享内存: ipcs -m
删除一条共享内存: ipcrm -m
拒绝演示.
共享内存相关的函数:
1.shmget函数
该函数用来创建共享内存.
int shmget(key_t key, size_t size, int shmflg);
参数:
key : 和信号量一样,程序需要提供一个参数key,它有效地为共享内存段命名。有一个特殊的键值IPC_PRIVATE, 它用于
创建一个只属于创建进程的共享内存,通常不会用到。
size: 以字节为单位指定需要共享的内存容量。
shmflag: 包含9个比特的权限标志,它们的作用与创建文件时使用的mode标志是一样。由IPC_CREAT定义的一个特殊
比特必须和权限标志按位或才能创建一个新的共享内存段。
NOTE:
权限标志对共享内存非常有用,因为它允许一个进程创建的共享内存可以被共享内存的创建者所拥有的进程写入,同时
其它用户创建的进程只能读取共享内存。
我们可以利用这个功能来提供一种有效的对数据进行只读访问的方法,通过将
数据放共享内存并设置它的权限,就可以避免数据被其他用户修改。
返回值:
创建成功,则返回一个非负整数,即共享内存标识;
如果失败,则返回-1.
2.shmat函数
第一次创建共享内存段时,它不能被任何进程访问。要想启动对该内存的访问
,必须
将其连接到一个进程的地址空间
void *shmat(int shm_id, const void *shm_addr, int shmflg);
参数:
shm_id:是由shmget函数返回的共享内存标识。
shm_addr:指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shm_flg:是一组标志位,通常为0。它的两个可能取值是:SHM_RND, 和shm_add联合使用,用来控制共享内存连接的
地址
SHM_RDONLY单独使用它使连接的内存只读.
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.
3.shmdt函数
将共享内存从当前进程中抽离.
int shmdt(const void *shm_addr);
hm_addr: shmat返回的地址指针。
成功时,返回0,
失败时,返回-1.
NOTE:
共享内存分离并未删除它,
只是使得该共享内存对当前进程不再可用。
4.
shmctl函数
共享内存控制函数.
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
参数:
shm_id : 是shmget返回的共享内存标识符。
command: 它可以取3个值:
IPC_STAT 把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET 如果进程有足够的权限就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID 删除共享内存段
buf:是一个指针,包含共享内存模式和访问权限的结构。
shmid_ds 一定要包含下列结构体.
struct shmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
总结:
1、优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进
程间
的
数
据不
用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定
的父子关系。
2、缺点:共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段来进
行进程
间
的同
步工作。