System v 共享内存

Mid  

最小的共享内存值  4K  /proc/sys/kernel/shmmin

最大的共享内存值 32M   /proc/sys/kernel/shmmax

可使用的共享内存总量 2M  /proc/sys/kernel/shmall

使用ipcs  可以查看共享内存的信息 但是mid上并没有包含该命令

下面简述pxa310 System v  共享内存的实现

Shmget 

创建或获取共享内存

ipc/shm.c

asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)

1        从当前进程的task_struct 中得到 ipc 的命名空间

 

struct ipc_namespace {

  struct kref   kref;

  struct ipc_ids     *ids[3];

 

  int          sem_ctls[4];

  int          used_sems;

 

  int          msg_ctlmax;

  int          msg_ctlmnb;

  int          msg_ctlmni;

 

  size_t            shm_ctlmax;

  size_t            shm_ctlall;

  int          shm_ctlmni;

  int          shm_tot;

};

 

其中 struct ipc_ids  *ids[3];

 对应着3IPC机制的ids,分别是信号量,消息队列,以及共享内存

这里只看共享内存的

2        判断传入的key 是否为 IPC_PRIVATE(0)

IPC_PRIVATE 表示是父子进程间内存共享

这个时候就需要创建一个新的共享段

将需求size 进行4K上取整,并取得所需page

如果之间的所有page数与当前page数大于2M ,则返回失败

如果这个size 小于1 或大于32M 则返回失败

 

每个共享内存区都有一个非常重要的数据结构

struct shmid_kernel /* private to the kernel */

{

  struct kern_ipc_perm    shm_perm;

  struct file *         shm_file;

  int                 id;

  unsigned long          shm_nattch;

  unsigned long          shm_segsz;

  time_t                 shm_atim;

  time_t                 shm_dtim;

  time_t                 shm_ctim;

  pid_t                   shm_cprid;

  pid_t                   shm_lprid;

  struct user_struct     *mlock_user;

};

这个数据结构非常重要,将存储管理和文件系统关联起来了

 shm_file 对应于特殊文件系统shm中的一个文件

访问路径 /proc/sysv/shm

 

 

分配了这样一个结构体后,将相应的key,flag 按照输入进行了设置,

将结构体指针放入 共享内存对应的ids 中的entries中。

 

              shmid_kernel 中的id 32768 * seq + 我们传入的id

             这个seq 存放在共享内存对应的ids 中,每次添加一个元素后++

             专门用来计算id

 如果共享内存不是用于父子进程间,

 首先就得在entries 中查找 ,指定的id是否存在

如果存在,但出入的flag 又指定必要创建,返回失败

否则创建新的shmid_kernel 放入ids中,流程与前面一样

如果找到了但没有创建标志

已经在的shmid_kernel结构中的大小不得小于本次调用传入的大小,否则失败

接下来检查用户,组和其他权限,

再次生存一个内部id号返回,计算公式和前面一致

 

Shmat

映射到进程的地址空间
asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)

1        首先对输入的shmid进行检查 

如果小于0,直接退出

 

如果用户设置了映射地址 shmaddr

检查该地址,是否是4K对齐的,如果没有对齐且有对齐标志

则下对齐,否则返回失败。

如果没有指定 shmaddr,但又置了remap标志,返回失败

 

根据shmflg 设置访问模式

 

找到对应的shmid_kernel 结构 ,使用前面提到的计算公式验证id

 

  shm_file中获取dentry和安装点

 

找出一个空闲的FILE 结构 ,设置 file_operations ,path ,地址空间 和私有数据后

调用do_mmap 进行映射

 

           首先需要找到一个没有影射过的区域

           怎么来找呢?

            前面设置file_operations 的时候设置了如下结构

 

 

static const struct file_operations shm_file_operations = {

  .mmap         = shm_mmap,

  .fsync           = shm_fsync,

  .release       = shm_release,

  .get_unmapped_area  = shm_get_unmapped_area,

};

 

就是调用 shm_get_unmapped_area 来获取一块没有影射的区域

 

对应 arch_get_unmapped_area

 

Arch/arm/mm/mmap.c

 

简单的说就是 生成一个满足条件的vm_area_struct,将其插入进程的虚拟地址描述符 构成的二叉树中。

 

 

 

 

           

 

 


 

Shmdt

asmlinkage long sys_shmdt(char __user *shmaddr)

将共享内存从当前进程中分离

首先通过 shmaddr 在二叉树中找到第一个满足块的结束地址大于shmaddr

 vm_area_struct 出来,如果满足条件就直接删掉。

 

…..

Shmctl

 

asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)

System V 共享内存

IPC_RMID 为例

通过 shmid找到对应的shmid_kernel

通过公式验证id

通过当前的进程的euid判断是否有权限

删除 对应的shmid_kernel 结构

总结

 

涉及到存储管理和文件系统。

System V 共享内存 是以文件的形式组织在特殊文件系统shm 中的,而shm的安装点在交换分区上 这样就决定了如下特点

1    从不写入磁盘文件,系统重新引导后内容消失

2     通信双方进程消失后 ,共享内存热然存在,除非显示删除。不用考虑进程终止对通信的影响。

3    没有实现同步。 需要与其他方式结合使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值