Linux 进程间通信(六)共享内存

版权声明:转载请声明 https://blog.csdn.net/qq_40732350/article/details/82843187

可以说, 共享内存是一种最为高效的进程间通信方式, 因为进程可以直接读写内存, 不需要任何数据的复制。 为了在多个进程间交换信息, 内核专门留出了一块内存区, 这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。 因此, 进程就可以直接读写这一内存区而不需要进行数据的复制, 从而大大提高了效率。 当然, 由于多个进程共享一段内存,因此也需要依靠某种同步机制, 如互斥锁和信号量等(请参考 4.7.2 节)。

其原理示意图如图4.7 所示。

先参考这个博客:

https://blog.csdn.net/tennysonsky/article/details/46425485

共享内存的实现分为两个步骤:

第一步是创建共享内存, 这里用到的函数是 shmget(),也就是从内存中获得一段共享内存区域;

第二步是映射共享内存, 也就是把这段创建的共享内存映射到具体的进程空间中, 这里使用的函数是 shmat()。

到这里, 就可以使用这段共享内存了, 也就是可以使用不带缓冲的 I/O 读写命令对其进行操作。

除此之外, 还有撤销映射的操作, 其函数为 shmdt()。 这里主要介绍这 3 个函数。
 

shmget()函数的语法要点。

函数原型

int shmget(key_t key, int size, int shmflg)

功能

创建获得共享内存

函数传入值
key: 共享内存的键值, 多个进程可以通过它访问同一个共享内存, 其中有个特殊值
IPC_PRIVATE, 用于创建当前进程的私有共享内存
size: 共享内存区大小
shmflg: 同 open()函数的权限位, 也可以用八进制表示法
函数返回值
成功: 共享内存段标识符
出错: 1

shmat()函数的语法要点。

函数原型

char *shmat(int shmid, const void *shmaddr, int shmflg)
函数传入值
shmid: 要映射的共享内存区标识符
shmaddr: 将共享内存映射到指定地址(若为 0 则表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)
shmflg:

  1. SHM_RDONLY: 共享内存只读
  2. 默认 0: 共享内存可读写

函数返回值
成功: 被映射的段地址
出错: 1

shmdt()函数的语法要点。

函数原型
int shmdt(const void *shmaddr)
函数参数

shmaddr: 被映射的共享内存段地址

函数返回值
成功: 0
出错: 1

shmctl()函数的语法要点。

函数原型

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

功能

对已存在的共享内存进行控制

函数参数

shmid:共享内存标识

cmd:操作类型

buf:指向操作的信息

返回值

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

cmd 含义
IPC_STAT 获取共享内存的状态
IPC_SET 设置共享内存的权限
IPC_RMID 删除共享内存
SHM_LOCK 锁定共享内存,使共享内存不被置换出去
SHM_UNLOCK 对共享内存 解锁

重要结构体:

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;    /* 创建进程ID */
               pid_t           shm_lpid;    /* 最近操作的进程ID */
               shmatt_t        shm_nattch;  /* 建立映射的进程数 */
               ...
           };
struct ipc_perm {
               key_t          __key;    /* Key supplied to shmget(2) */
               uid_t          uid;      /* Effective UID of owner */
               gid_t          gid;      /* Effective GID of owner */
               uid_t          cuid;     /* Effective UID of creator */
               gid_t          cgid;     /* Effective GID of creator */
               unsigned short mode;     /* Permissions + SHM_DEST and
                                           SHM_LOCKED flags */
               unsigned short __seq;    /* Sequence number */
           };

猜你喜欢

转载自blog.csdn.net/qq_40732350/article/details/82843187