1.定义key
生成一个任意不重复的key作为整个系统生命周期的内存标识;
例如ftok();根据特定序列或者文件名生成唯一key;也可以手动指定
2.开辟共享内存:
shmget(key,size,flag);
key:标识
size: 共享内存大小,单位byte
flag:权限位,一般创建时|IPC_CREAT,如果|ICP_EXCL则只能新建,已有就报错
返回值:shmid, 此ID作用于内核存续生命周期的共享内存标识
2.1打开已有的共享内存
shmget(key,0,0)
key:标识
返回值:shmid
2.2获取共享内存属性
定义一个 struct shmid_ds buf结构体
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};
shmctl(shmid,IPC_STAT,buf);
此时这个buf.shm_segsz就是获取的共享内存大小
3.映射共享内存地址到进程地址空间
用户进程的地址是通过页表映射到物理地址的,共享内存的地址也需要映射后才能被用户进程调用
void *pshm
pshm=shmat(shmid,NULL,SHM_RND);
shmid:如上获取
NULL:这里如果有权限,可以自己指定虚拟地址
SHM_RND:还可以设定SHM_RDONLY只读,这里是读写权限
4.使用完毕后删除映射(内存还在,内核管理在)
shmdt(pshm)
这里pshm是之前映射好的地址指针。
5.删除共享内存
shmctl(shmid,IPC_SET,IPC_RMID)
shmid:如上2获取
IPC_SET:这个上面用IPC_STAT获取内存信息,这里IPC_SET就是设置内存信息,权限充足的情况下,也可以通过定义好的信息结构体来设定详细的共享内存结构
IPC_RMID:标志位删除,不会立即删除,最后一个引用该内存的进程退出后由内核删除。