【Unix环境编程】进程通信——IPC共享内存学习

 

参考书籍:<linxu程序设计第2><linux系统分析和高级编程技术><linux内核完全注释>

共享内存即让两个进程访问同一部分逻辑内存。是有IPC为一个进程创建的特殊的地址范围,出现在进程的地址空间中,其他进程可以把同一段共享内存段连接到它们自己的地址空间去。如果一个进程向这段共享内存写了数据,所做的改变立刻被其他进程看到。但是共享内存本身没有同步功能,需要我们自己注意同步。

1.共享内存相关结构体定义以及函数声明:系统的共享内存段在系统内核中也有一个内部的数据结构shmid_ds。描述了共享内存的认证,字节大小,分离、改变时间,创建它的进程,最后操作的进程以及多少进程在使用等信息。这些数据结构保存在 shm_segs 向量表中,struct shmid_ds不是内核用来跟踪共享内存区域的数据结构。取而代之的是,struct shmid_ds包含这种信息的绝大部分,而剩下的信息则位于下边要介绍的struct shmid_kernel中。Shmid_dsLinux/shm.h中有定义:

 

 

 

相关头文件sys/shm.h sys/ipc.h sys/types.hipc/shm.c里有对应内核源码。这是shm.h里关于共享内存函数的声明。

 

共享内存处理函数中使用的一些宏:系统中共享内存数量是限制宏和共享内存出来函数中使用的flag

shm.c文件中 定义了共享内存例外的几个属性:

 

struct shmid_kernel用于分离“私有(private)”的共享内存相关信息和“公有(public)”的信息。struct shmid_ds里那些对用户应用程序可见的部分还保留在struct shmid _ds之内,而关系到内核的私有信息则位于struct shmid_kernel之内。用户应用程序需要能够通过struct shmid_ds来进行shmctl系统调用,所以它的定义必须对它们是可见的,但是内核私有实现的细节就不应该出现在struct的定义之中。否则,改变内核的执行可能会中断应用程序。

3.共享内存函数解析

shmget():创建共享内存。程序需要一个键字参数key也就是共享内存段的名字,shmget返回一个供后续共享内存函数使用的共享内存标识码。首先系统是调用sys_ipcipc.c内)call值为SHMGET创建一个键值为key的共享内存对象,或者获得已经存在的键值为key的某共享内存对象的引用标识符。Size表需要共享的内存量,字节为单位。Shmflg9个权限标志。IPC_CREAT和其他标志或在一起才能创建新的共享内存段。使用方法和open函数的mode参数类似。

Sys_ipc函数:

 

Sys_semget函数:

 

    Sys_semget函数流程:Key=IPC_PRIVATE时穿件本进程的私有共享内存。Sys_shmgetnewseg函数与newquenewary相对应的函数,主要工作是计算size大小,申请shmid_kernel数据结构,申请一块用于建立页表的空间并清零,填写shmid_kernel数据结构并加入到shm_segs中,返回共享内存对象的引用标识符,struct shmid_kernel是由kmalloc分配的(在不可交换的内核内存里)。Key有值的时候,如果在没有在shm_segs中找到键值为key的共享内存对象,检测传入的shmflg,如果shmflg需要创建则创建,否则返回错误。如果找到,根据shmflg判断是否要求创建,要求创建返回错误,不要求创建并且检测shm_lock()返回的shmid_kernel结构体是否合法,合法返回对象的标识符。

键:在IPC的通信模式下,不管是使用消息队列还是共享内存,甚至是信号量,每个IPC的对象(object)都有唯一的名字,称为“键”(key)。通过“键”,进程能够识别所用的对象。“键”与IPC对象的关系就如同文件名称之于文件,通过文件名,进程能够读写文件内的数据,甚至多个进程能够共用一个文件。而在IPC的通讯模式下,通过“键”的使用也使得一个IPC对象能为多个进程所共用。 Linux系统中的所有表示SystemVIPC对象的数据结构都包括一个ipc_perm结构,其中包含有IPC对象的键值,该键用于查找SystemVIPC对象的引用标识符。如果不使用“键”,进程将无法存取IPC对象,因为IPC对象并不存在于进程本身使用的内存中。

Shmat()把建立的共享内存段连接到某个进程的地址空间以便访问。第一个参数shm_idshmget返回的标识码,shm_addr是共享内存连接到当前进程时准备放置的地址,如果是空指针表把该工作交给系统完成。Shmflg处理标识,SHM_RNDSHM_RDONLY。返回的是进程中虚拟地址。

Shmat()函数:

 

Kernelsys_shmat()函数首先是根据shmid找到共享内存对象。根据shmaddr的地址座位映射的虚拟地址,当shmaddr0时,随机分配一个。检查虚拟地址合法性,申请一块用来建vm_area_struct结构内存,并填写,加入到进程的mm结构和该共享内存对象的vm_area_struct队列中。

Shmdt函数时把共享内存与当前进程脱离开。参数是shmget返回的地址指针。不影响其他进程和该共享内存对象的交互。当前进程的vm_area_struct结构被从shmid_ds中删除释放,进程的页表也被更新,当该共享内存和最后一个进程也分离,则共享内存页和kemid_kernel结构也都被释放。

Sys_shmdt函数: 

Shmctl函数,共享内存的控制函数。参数command表将要采取的动作:IPC_STAT,SHM_STAT shmid_ds结构中的数据设置为共享内存的当前关联值,IPC_SET在进程有权限下把共享内存的当前关联值设为shmid_ds给的值,IPC_RMID删除共享内存段,获得共享内存状态(SHM_INFO IPC_INFO),锁定和释放(SHM_LOCKED)等。参数buf是指向shmid_ds结构体的指针。

shmctl函数:

实例(linux程序设计源码):

shm_com.h

shm1.c

shm2.c

实例的共享内存大小为shared_use_st结构体大小,shm1.c shm2.c 通过结构体第一个变量wtiteen_by_you实现两个进程对共享内存区域的同步操作。读写的内容保存到buffer中。首先创建共享内存段,连接。然后shm1.c持续读共享内存中内容,shm2.c持续写共享到共享内存中,以字符串end结束。共享内存从进程分离并删除。

用两个shh登陆分别运行1和2程序:

Ipcs –mipcrm shm <id>命令:

ipcs -m 可以看我们的系统共享内存情况,ipcrm shm <id>可以删除共享内存。运行1程序后直接ctrl c中止进程,我们就没有释放申请的共享内存段,我们用ipcrm shm释放共享内存。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值