一、共享内存是什么
共享内存是两个进程之间最快的也是最有用的通信方式。
由于之前我们所介绍的通讯方式都要进过内核和自己的用户空间之间进行传递,而共享内存则是进程直接把内存映射到自己进程的地址空间内,所以A进程和B进程可直接看到对方对这块区域所进行的操作。
由于进程可以直接读写内存,并不需要任何的数据的拷贝,这一点和前面所介绍的进程间的通信就不一样,所以它的效率很高,换句话说,进程不再通过执行进入内核的系统调用来传递彼此的数据。
二、共享内存的结构
和介绍之前的进程间通信一样,我们来看下下面共享内存的结构。
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 */
...
};
三、共享内存的函数
(1)shmget
shmget函数用来创建共享内存。
- 函数原型
int shmget(key_t key, size_t size, int shmflg);
- 参数
- key_t key:第一个参数是和消息队列中的key是一样的,表示共享内存的名字。
- size_t size:第二个参数指的是多大的空间
- int shmflg:是权限,有九个标志位。可以是IPC_CREAT | 0644
- 返回值
成功返回一个非负的整数,即该共享内存的标识符,失败返回-1
(2)shmat
将共享内存挂在自己的地址空间上
void *shmat(int shmid, const void *shmaddr, int shmflg);
- 返回值
成功返回0,失败返回-1 - 参数
- shmid:共享内存标志。
- shmaddr:指定链接的地址,一般情况下我们取NULL,表示自动选取一个地址。
- shmflg:标记,两个可能的取值为SHM_RND和SHM_RDONLY,一般情况下取0。
(3)shmdt
我们需要注意的是共享内存的删除是没有人映射的时候才可以删除,他和消息队列不一样,有人映射的时候是无法删除。
将不用的共享内存从自己的地址空间删除。
int shmdt(const void *shmaddr);
- 参数:
由shmdt返回的指针。 - 返回值
成功返回0,失败返回-1
(4)shmctl
shmctl用来控制共享内存。
nt shmctl(int shmid, int cmd, struct shmid_ds *buf);
- 参数
- shmid:由shmget返回共享内存的标识符
- cmd:将要采取的动作
- buf:指向一个保存共享内存的模式状态和访问权限的数据结构
- 返回值
成功返回0,失败返回-1
cmd有以下三个命令可供选择,这个和消息队列的ctl操作很类似
- IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值
- IPC_SET:有足够的权限下,会把共享内存的当前值设置为由shmid_ds数据结构中给出的值
- IPC_RMID:删除共享内存
四、如何读共享内存
直接读自己的进程空间,因为此时内存映射到了进程地址空间内。