共享存储

2015-05-16 21:01:40   最后更新: 2015-05-16 21:01:40   访问数量:617




共享内存允许两个或更多个进程共享一个给定的存储区域,这是最快的一种 IPC

但是,当某个进程正在读写共享存储的某个区域时,其他进程同时不应该对该区域进行操作,信号量通常被用来实现对共享存储访问的同步,当然,记录所也可以用于这种场合,但是记录锁在时间上要比信号量多消耗约 60%

 

内核为每个共享存储段设置了一个 shmid_ds 结构

struct shmid_ds { struct ipc_perm shm_perm; // 权限结构 size_t shm_segsz; // 存储段大小(字节数) pid_t shm_lpid; // 最后一个操作共享内存段的进程 ID pid_t shm_cpid; // 创建共享内存段的进程 ID shmatt_t shm_nattch; // 连接计数 time_t shm_atime; // 最后执行 attach 操作的时间 time_t shm_dtime; // 最后执行 detach 操作的时间 time_t shm_ctime; // 最后执行 change 操作的时间 ... ... }

 

各系统的具体实现会包含额外的字段

 

函数 shmget 用于创建一个新的共享存储段或获取一个已经存在的共享存储段

int shmget(key_t key, size_t size, int flag);

 

定义于 sys/shm.h 中

成功调用返回共享存储段 ID,否则返回 -1

 

该函数将 key 变换为信号量集标识符,并返回,与消息队列创建函数 msgget 一样:

  1. 如果 key 取值为 IPC_PRIVATE,则创建新的 IPC 结构
  2. 如果指定的 key 当前未与任何 IPC 结构结合,并且 flag 中指定了 IPC_CREAT 位,则用该 key 创建新的 IPC 结构
  3. 如果指定的 key 当前未与任何 IPC 结构结合,并且 flag 中未指定 IPC_CREAT 位,则函数返回出错
  4. 如果指定的 key 当前已经与 IPC 结构结合,并且 flag 中未指定 IPC_EXECL 位,则返回对应 IPC 结构,否则返回 EEXIST

 

参数 nsems 用于初始化该信号量集描述结构的 sem_nsems 字段

 

shmctl 函数可以执行多种操作,与 ioctl、semctl、shmctl 非常类似,都被称为“垃圾桶函数”

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

 

定义于 sys/shm.h 中

调用成功返回 0,否则返回 -1

 

cmd 参数可以指定下列 5 种命令的一种

shmctl 函数 cmd 参数取值
取值意义
IPC_STAT获取 shmid 对应的存储段描述结构 shmid_ds 并存储在参数 buf 所指向的内存中
IPC_SET按 buf 所指向内存中的 shmid_ds 结构设置 shmid 对应的存储段描述结构(可以改变 shm_perm.uid、shm_perm.gid、shm_perm.mode),执行此命令的进程有效用户 ID 必须等于 sem_perm.cuid 或 sem_perm.uid 或者该进程具有超级用户权限
IPC_RMID从系统中删除该共享存储段,与其他两个 XSI IPC 的相应操作不同,执行后并不会立即删除,除非该存储段的最后一个进程终止或与该段脱离连接(shm_nattch 值变为 0),执行此命令的进程有效用户 ID 必须等于 sem_perm.cuid 或 sem_perm.uid 或者该进程具有超级用户权限
SHM_LOCK将共享存储段锁定在内存中,只有超级用户可以执行此命令
SHM_UNLOCK解锁共享内存段,只有超级用户可以执行此命令

 

一旦创建了一个共享存储段,进程就可以通过调用 shmat 函数将它连接到它的地址空间中:

void *shmat(int shmid, const void *addr, int flag);

 

定义于 sys/shm.h 中

调用成功返回指向共享存储地址空间的指针,否则返回 -1

 

addr 参数说明

若 addr 为 0,则此段连接到有内核选择的第一个可用地址上(推荐使用)

若 addr 不为 0,则需要参考 flag 参数的值

 

flag 参数说明

flag 可以取下列宏的与

shmat 函数 flag 参数取值
取值意义
SHM_RND连接到 addr 最近的一个 2 的乘方地址上(若未指定该标识,则直接连接到 addr 指向的地址)
SHM_RDONLY连接后,该段只能被以只读方式使用(若未指定该标志,则以读写方式使用)

 

shmat 相反的操作即脱离连接,就是 shmdt 函数

int shmdt(void *addr);

 

定义于 sys/shm.h 中

调用成功返回 0,否则返回 -1

 

shmdt 的实际操作是将 shm_nattch 的值减 1

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      内存      memory      存储      mmap      共享存储      cache      shm      share memory      shmget      shmctl      shmat      shmdt     


京ICP备15018585号