四、共享内存
1.基本特点
(1) 两个或者更多进程,共享同一块由系统内核负责维护的内存区域,其地址空间通常被映射到堆和栈之间。
(2) 无需复制信息,最快的一种IPC机制。
(3) 需要考虑同步访问的问题。
(4) 内核为每个共享内存,维护一个shmid_ds结构体形式的共享内存对象。
2.常用函数
#include <sys/shm.h>
(1) 创建/获取共享内存
int shmget (key_t key, size_t size, int shmflg);
A. 该函数以key参数为键值创建共享内存,或获取已有的共享内存。
B. size参数为共享内存的字节数, 建议取内存页字节数(4096)的整数倍。
若希望创建共享内存,则必需指定size参数。
若只为获取已有的共享内存,则size参数可取0。
C. shmflg取值:
0 - 获取,不存在即失败。
IPC_CREAT - 创建,不存在即创建,
已存在即获取,除非…
IPC_EXCL - 排斥,已存在即失败。
D. 成功返回共享内存标识,失败返回-1。
(2) 加载共享内存
void* shmat (int shmid, const void* shmaddr,int shmflg);
A. 将shmid参数所标识的共享内存,映射到调用进程的地址空间。
B. 可通过shmaddr参数人为指定映射地址,也可将该参数置NULL,由系统自动选择。
C. shmflg取值:
0 - 以读写方式使用共享内存。
SHM_RDONLY - 以只读方式使用共享内存。
SHM_RND - 只在shmaddr参数非NULL时起作用。
表示对该参数向下取内存页的整数倍,作为映射地址。
D. 成功返回映射地址,失败返回-1。
E. 内核将该共享内存的加载计数加1。
(3) 卸载共享内存
int shmdt (const void* shmaddr);
A. 从调用进程的地址空间中,取消由shmaddr参数所指向的,共享内存映射区域。
B. 成功返回0,失败返回-1。
C. 内核将该共享内存的加载计数减1。
(4) 销毁/控制共享内存
int shmctl (int shmid, int cmd, struct shmid_ds* buf);
A. cmd取值:
IPC_STAT
获取共享内存的属性,通过buf参数输出。
IPC_SET
设置共享内存的属性,通过buf参数输入,仅以下三个属性可设置:
shmid_ds::shm_perm.uid
shmid_ds::shm_perm.gid
shmid_ds::shm_perm.mode
IPC_RMID
标记删除共享内存。
并非真正删除共享内存,只是做一个删除标记,禁止其被继续加载,但已有加载依然保留。
只有当该共享内存的加载计数为0时,才真正被删除。
B. 成功返回0,失败返回-1。
struct shmid_ds
{
struct ipc_perm shm_perm; // 所有者及其权限
size_t shm_segsz; // 大小(以字节为单位)
time_t shm_atime; // 最后加载时间
time_t shm_dtime; // 最后卸载时间
time_t shm_ctime; // 最后改变时间
pid_t shm_cpid; // 创建进程PID
pid_t shm_lpid; // 最后加载/卸载进程PID
shmatt_t shm_nattch; // 当前加载计数
...
};
struct ipc_perm
{
key_t __key; // 键值
uid_t uid; // 有效属主ID
gid_t gid; // 有效属组ID
uid_t cuid; // 有效创建者ID
gid_t cgid; // 有效创建组ID
unsigned short mode; // 权限字
unsigned short __seq; // 序列号
};
- 编程模型
范例:wshm.c、rshm.c
wshm.c
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
int main ()
{
printf ("创建共享内存...\n");
key_t key = ftok (".", 100);
if (key == -1)
{
perror