【Linux】Linux进程间通信之共享内存
1、共享内存概念引入
共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据
2、共享内存数据结构
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};
3、先来介绍一下共享内存所需要的函数
(1)shmget函数
函数原型:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size,int shmflg);
功能:
用来创建共享内存
参数解释:
参数一:这个共享内存段名字
参数二:共享内存大小
参数三:权限位,有九个选项,与创建文件时的权限相同
返回值;
成功返回一个非负整数,即该共享内存的标识码,失败返回-1
(2)shmat函数
函数原型:
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数功能·:
将共享内存段连接到进程地址空间
参数解释:
参数一:共享内存标识码
参数二:指针,指定连接的地址
参数三:有两个取值,可能为SHM_RND和SHM_RDONLY
返回值:
成功返回一个指针,指向共享内存的第一节,失败返回-1
说明:
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
(3)shmdt函数
函数原型:
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
函数功能·:
将进程与当前共享内存脱离
参数解释:
由shmat返回的指针
返回值:
成功返回0,失败返回-1
说明:将进程与当前共享内存段分离与删除此共享内存段是不同的
(4)shmctl函数
函数原型:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
函数功能:
用于控制共享内存
函数参数解释:
参数一:共享内存标识码
参数二:将要采取的动作,一共有三个选择·,IPC_STAT,IPC_RMID,IPC_SET
参数三:一个结构体的实例
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 */
...
};
返回值:
成功返回0,失败返回-1
实例代码:
comm.h
comm.c
server.c
client.c
运行结果:
说明:代码的实质是将两个进程都连接到共享内存上,用client向共享内存中写数据,用server往外读数据,两个进程看到一片共同的内存。
和消息队列一样,共享内存也是随内核的,必须用指令来删除,使用 ipcs -m 列出所有的共享内存
使用ipcrm -m 删除共享内存