Linux进程间通讯五--共享内存

一、共享内存IPC原理

  共享内存进程间通信机制主要用于实现进程间大量数据传输,共享内存是在内存(用户空间不是内核空间)中单独开辟出来的一段内存空间。下图为进程间通信示意图:
  这里写图片描述
  两个进程在使用此共享内存空间之前,需要在进程地址空间与共享内存空间之间建立联系,即将共享内存空间挂载到进程中。
  在使用共享内存进行数据存取时,有必要使用二元信号量来同步两个进程以实现对共享内存的写操作。由于共享内存需要占用大量的内存空间,系统对共享内存做了一下限制:

#define SHMMAX 0x2000000                 /* max shared seg size (bytes) */
#define SHMMIN 1                         /* min shared seg size (bytes) */
#define SHMMNI 4096                      /* max num of segs system wide */
#define SHMALL (SHMMAX/getpagesize()*(SHMMNI/16))
#define SHMSEG SHMMNI                    /* max shared segs per process */
二、共享内存管理

1.创建共享内存
  创建共享内存的系统调用shmget()函数声明如下:

// come from /usr/include/sys/shm.h
int shmget(key_t key, size_t size, int shmflg);

  第1个参数为key值,有ftok()函数产生,关于ftok函数在我的博客《System V IPC基础》一节有说明。;
  第2个参数size为欲创建共享内存的大小(单位为字节);
  第3个参数shmflg用来标识共享内存段的创建标识,包括:

#define IPC_CREAT       01000   /* Create key if key does not exist. */ // 如果key不存在,则创建,存在,返回ID
#define IPC_EXCL        02000   /* Fail if key exists.  */              // 如果key存在返回失败
#define IPC_NOWAIT      04000   /* Return error on wait.  */            // 如果需要等待,直接返回错误

  另外在/usr/include/linux/shm.h文件中还定义了另外两个选项:

/* permission flag for shmget */
#define SHM_R           0400    /* or S_IRUGO from <linux/stat.h> */    // 可读
#define SHM_W           0200    /* or S_IWUGO from <linux/stat.h> */    // 可写

  下面给出创建共享内存的代码:

#include <sys/shm.h>

key_t key = ftok("/", 3);
int shmid = shmget(key, 100, IPC_CREAT | 0666);

2.共享内存控制
  Linux系统使用shmctl()函数来实现共享内存空间的控制,包括读取状态设置状态删除操作,此函数声明如下:

// come from /usr/include/sys/shm.h
int shmctl(int shmid, int cmd, struct shmid_ds* buf);

  第1个参数shmid为要操作的共享内存标识符,由shmget()函数返回;
  第2个参数为要执行的操作,具体包括以下:

// come from /usr/include/linux/ipc.h
#define IPC_RMID 0     /* remove resource */        // 删除共享内存
#define IPC_SET  1     /* set ipc_perm options */   // 设置ipc_perm参数
#define IPC_STAT 2     /* get ipc_perm options */   // 获取ipc_perm参数
#define IPC_INFO 3     /* see ipcs */               // 获取限制信息

  如果是超级用户,还可以执行下面两个命令:

/* super user shmctl commands */
#define SHM_LOCK        11    // 锁定共享内存段
#define SHM_UNLOCK      12    // 解锁共享内存段

  第3个参数为struct shmid_ds结构的临时共享内存变量信息,此内容根据第2个参数的不同而改变。
  
  下面为删除共享内存的代码:

shmctl(shmid, IPC_RMID, NULL);

3.映射共享内存
  在进程使用一段共享内存空间之前,需要将该共享内存与当前进程建立联系,即将该共享内存映射(挂接)到当前进程。系统调用shmat()实现将一个共享内存段映射到调用进程的数据段中,并返回该内存空间首地址,其函数声明如下:

// come from /usr/include/sys/shm.h
void* shmat(int shmid, const void* shmaddr, int shmflg);

  第1个参数shmid为要操作的共享内存段首地址,该值由shmget()函数返回;
  第2个参数shmaddr指定共享内存的映射地址。如果该值为非零,则将用此值作为映射共享内存的地址,如果为0,则由系统来选择映射地址。一般都将此值设置为0
  第3个参数用来指定共享内存的访问权限映射条件

/* mode for attach */
#define SHM_RDONLY      010000  /* read-only access */
#define SHM_RND         020000  /* round attach address to SHMLBA boundary */
#define SHM_REMAP       040000  /* take-over region on attach */
#define SHM_EXEC        0100000 /* execution access */

  若设置为0,则默认有读写的权限。
  
  下面为将共享内存映射到进程空间的代码:

char* p = (char*)shmat(shmid, NULL, 0);

4.分离共享内存
  在使用完共享内存空间后,需要使用shmdt()函数将其与当前进程分离,shmdt()函数的声明如下:

// come from /usr/include/sys/shm.h
int shmdt(const void* shmaddr);

  该函数只有一个参数,即为通过映射函数shmat()返回的地址。需要注意的是在删除共享内存之前需要先分离

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值