shmget物理内存_shmget共享内存

shmget物理内存_shmget共享内存Linux 为共享内存提供了四种操作 1 共享内存对象的创建或获得 与其它两种 IPC 机制一样 进程在使用共享内存区域以前 必须通过系统调用 sys ipc call 值为 SHMGET 创建一个键值为 key 的共享内存对象 或获得已经存在的键值为 key 的某共享内存对象的引用标识符 以后对共享内存对象的访问都通过该引用标识符进行 对共享内存对象的创建或获得由函数 sys shmget 完成 其定义如下 int

Linux为共享内存提供了四种操作。

1. 共享内存对象的创建或获得。与其它两种IPC机制一样,进程在使用共享内存区域以前,必须通过系统调用sys_ipc (call值为SHMGET)创建一个键值为key的共享内存对象,或获得已经存在的键值为key的某共享内存对象的引用标识符。以后对共享内存对象的访问都通过该引用标识符进行。对共享内存对象的创建或获得由函数sys_shmget完成,其定义如下:

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

这里key是表示该共享内存对象的键值,size是该共享内存区域的大小(以字节为单位),shmflg是标志(对该共享内存对象的特殊要求)。

它所做的工作如下:

1) 如果key == IPC_PRIVATE,则总是会创建一个新的共享内存对象。

但是  (The name choice IPC_PRIVATE was perhaps unfortunate, IPC_NEW would more clearly show its function)

* 算出size要占用的页数,检查其合法性。

* 申请一块内存用于建立shmid_kernel数据结构,注意这里申请的内存区域大小不包括真正的共享内存区,实际上,要等到第一个进程试图访问它的时候才真正创建共享内存区。

* 根据该共享内存区所占用的页数,为其申请一块空间用于建立页表(每页4个字节),将页表清0。

* 搜索向量表shm_segs,为新创建的共享内存对象找一个空位置。

* 填写shmid_kernel数据结构,将其加入到向量表shm_segs中为其找到的空位置。

* 返回该共享内存对象的引用标识符。

2) 在向量表shm_segs中查找键值为key的共享内存对象,结果有三:

* 如果没有找到,而且在操作标志shmflg中没有指明要创建新共享内存,则错误返回,否则创建一个新的共享内存对象。

* 如果找到了,但该次操作要求必须创建一个键值为key的新对象,那么错误返回。

* 否则,合法性、认证检查,如有错,则错误返回;否则,返回该内存对象的引用标识符。

共享内存对象的创建者可以控制对于这块内存的访问权限和它的key是公开还是私有。如果有足够的权限,它也可以把共享内存锁定在物理内存中。

参见include/linux/shm.h

2. 关联。在创建或获得某个共享内存区域的引用标识符后,还必须将共享内存区域映射(粘附)到进程的虚拟地址空间,然后才能使用该共享内存区域。系统调用 sys_ipc(call值为SHMAT)用于共享内存区到进程虚拟地址空间的映射,而真正完成粘附动作的是函数sys_shmat,

其定义如下:

#include

#include

void *shmat(int shmid, const void *shmaddr, int shmflg);

其中:

shmid是shmget返回的共享内存对象的引用标识符;

shmaddr用来指定该共享内存区域在进程的虚拟地址空间对应的虚拟地址;

shmflg是映射标志;

返回的是在进程中的虚拟地址

该函数所做的工作如下:

1) 根据shmid找到共享内存对象。

2) 如果shmaddr为0,即用户没有指定该共享内存区域在它的虚拟空间中的位置,则由系统在进程的虚拟地址空间中为其找一块区域(从1G开始);否则,就用shmaddr作为映射的虚拟地址。

(If  shmaddr  is NULL, the system chooses a suitable (unused) address a他 which to attach the segment)

3) 检查虚拟地址的合法性(不能超过进程的最大虚拟空间大小—3G,不能太接近堆栈栈顶)。

4) 认证检查。

5) 申请一块内存用于建立数据结构vm_area_struct,填写该结构。

6) 检查该内存区域,将其加入到进程的mm结构和该共享内存对象的vm_area_struct队列中。

共享内存的粘附只是创建一个vm_area_struct数据结构,并将其加入到相应的队列中,此时并没有创建真正的共享内存页。

当进程第一次访问共享虚拟内存的某页时,因为所有的共享内存页还都没有分配,所以会发生一个page fault异常。当Linux处理这个page fault的时候,它找到发生异常的虚拟地址所在的vm_area_struct数据结构。在该数据结构中包含有这类共享虚拟内存的一组处理程序,其中的 nopage操作用来处理虚拟页对应的物理页不存在的情况。对共享内存,该操作是shm_nopage(定义在ipc/shm.c中)。该操作在描述这个共享内存的shmid_kernel数据结构的页表shm_pages中查找发生page fault异常的虚拟地址所对应的页表条目,看共享页是否存在(页表条目为0,表示共享页是第一次使用)。如果不存在,它就分配一个物理页,并为它创建一个页表条目。这个条目不但进入当前进程的页表,同时也存到shmid_kernel数据结构的页表shm_pages中。

当下一个进程试图访问这块内存并得到一个page fault的时候,经过同样的路径,也会走到函数shm_nopage。此时,该函数查看shmid_kernel数据结构的页表shm_pages时,发现共享页已经存在,它只需把这里的页表项填到进程页表的相应位置即可,而不需要重新创建物理页。所以,是第一个访问共享内存页的进程使得这一页被创建,而随后访问它的其它进程仅把此页加到它们的虚拟地址空间。

3. 分离。当进程不再需要共享虚拟内存的时候,它们与之分离(detach)。只要仍旧有其它进程在使用这块内存,这种分离就只会影响当前的进程,而不会影响其它进程。当前进程的vm_area_struct数据结构被从shmid_ds中删除,并被释放。当前进程的页表也被更新,共享内存对应的虚拟内存页被标记为无效。当共享这块内存的最后一个进程与之分离时,共享内存页被释放,同时,这块共享内存的shmid_kernel数据结构也被释放。

系统调用sys_ipc (call值为SHMDT) 用于共享内存区与进程虚拟地址空间的分离,而真正完成分离动作的是函数sys_shmdt,其定义如下:

int sys_shmdt (char *shmaddr)

其中shmaddr是进程要分离的共享页的开始虚拟地址。

该函数搜索进程的内存结构中的所有vm_area_struct数据结构,找到地址shmaddr对应的一个,调用函数do_munmap将其释放。

在函数do_munmap中,将要释放的vm_area_struct数据结构从进程的虚拟内存中摘下,清除它在进程页表中对应的页表项(可能占多个页表项).

如果共享的虚拟内存没有被锁定在物理内存中,分离会更加复杂。因为在这种情况下,共享内存的页可能在系统大量使用内存的时候被交换到系统的交换磁盘。为了避免这种情况,可以通过下面的控制操作,将某共享内存页锁定在物理内存不允许向外交换。共享内存的换出和换入,已在第3章中讨论。

4. 控制。Linux在共享内存上实现的第四种操作是共享内存的控制(call值为SHMCTL的sys_ipc调用),它由函数sys_shmctl实现。控制操作包括获得共享内存对象的状态,设置共享内存对象的参数(如uid、gid、mode、ctime等),将共享内存对象在内存中锁定和释放(在对象的mode上增加或去除SHM_LOCKED标志),释放共享内存对象资源等。

共享内存提供了一种快速灵活的机制,它允许进程之间直接共享大量的数据,而无须使用拷贝或系统调用。共享内存的主要局限性是它不能提供同步,如果两个进程企图修改相同的共享内存区域,由于内核不能串行化这些动作,因此写的数据可能任意地互相混合。所以使用共享内存的进程必须设计它们自己的同步协议,如用信号灯等。

以下是使用共享内存机制进行进程间通信的基本操作:

需要包含的头文件:

#include

#include

#include

1.创建共享内存:

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

参数说明:

key:用来表示新建或者已经存在的共享内存去的关键字。

size:创建共享内存的大小。

shmflg:可以指定的特殊标志。IPC_CREATE,IPC_EXCL以及低九位的权限。

eg:

int shmid;

shmid=shmget(IPC_PRIVATE,4096,IPC_CREATE|IPC_EXCL|0660);

if(shmid==-1)

perror(“shmget()”);

2.连接共享内存

char *shmat(int shmid,char *shmaddr,int shmflg);

参数说明

shmid:共享内存的关键字

shmaddr:指定共享内存出现在进程内存地址的什么位置,通常我们让内核自己决定一个合适的地址位置,用的时候设为0。

shmflg:制定特殊的标志位。

eg:

int shmid;

char *shmp;

shmp=shmat(shmid,0,0);

if(shmp==(char *)(-1))

perror(“shmat()\n”);

3.使用共享内存

在使用共享内存是需要注意的是,为防止内存访问冲突,我们一般与信号量结合使用。

4.分离共享内存:当程序不再需要共享内后,我们需要将共享内存分离以便对其进行释放,分离共享内存的函数原形如下:

int shmdt(char *shmaddr);

5. 释放共享内存

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

*示例

int *__accept_socketfd;

int shmid = shmget(SHAREMEMID,sizeof(int),IPC_CREAT|0666);

if (( __accept_socketfd = (int *)shmat(shmid,NULL,0 )) == (int *)-1 )

{

printf(“Error:shmat\n”);

return;

}

*__accept_socketfd = 0;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206256.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午4:06
下一篇 2026年3月19日 下午4:06


相关推荐

  • 深入理解协方差(图文详解)

    深入理解协方差(图文详解)先从方差开始 我们有一组样本 x1 x2 x3 xn 这组样本的均值为 EX 每一个样本都与 EX 之间存在误差 那么这组样本的方差被定义为 所有误差的和的均值 也即 xi EX 2 n 1 方差的作用就是用来 衡量样本偏离均值的程度 下面开始看协方差 仔细观察上述定义式 可知 如果两个变量的变化趋势一致 也就是说如果其中一个大于自身的期望值时另外一个也大于自身的

    2026年3月18日
    1
  • android开发之使用SQLite数据库存储

    SQLite 介绍SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla, PHP, Python)都使用了 SQLite.SQLite 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQL

    2022年3月10日
    46
  • 磁盘在磁盘管理中显示没有初始化找回文件方案「建议收藏」

    磁盘在磁盘管理中显示没有初始化找回文件方案「建议收藏」磁盘没有初始化是因为0号扇区损坏,导致机械硬盘分区表读取不出来,从而机械硬盘出现磁盘没有初始化。工具/软件:极限数据恢复软件步骤1:程序打开后,直接双击需要恢复数据的物理盘。步骤2:等待程序扫描完毕大概需要几分钟到半个小时,稍微耐心等下即可。步骤3:软件扫描到资料后,软件会将扫描到的分区列出来。步骤4:勾上所有需要恢复的资料,右击选择《复制勾选的文件》,…

    2026年2月10日
    4
  • 计算机机房安全设计规范,弱电机房建设规范要求

    计算机机房安全设计规范,弱电机房建设规范要求原标题:弱电机房建设规范要求工程中的数据中心机房建设是保证计算机网络设备和各级工作保障系统正常运转的关键。现在的计算机设备对运行环境要求较高。因此,必须按照一定的标准规范科学地设计机房。机房建设需要执行的标准主机房建设工程必须遵循国家机房设计标准规范的要求。场地要求计算机机房在多层建筑或高层建筑物内一般应设于第二、三层,水源充足,电力稳定可靠,应远离产生粉尘、油烟、有害气体以及贮存具有腐蚀性、易燃…

    2022年10月2日
    4
  • 网站开发团队成员(项目团队)

    1.项目带头人(Boss):通常是项目的发起人,为项目规划企业战略目标,对项目的成败负最终责任。2.项目经理:这个不用说了是项目当然需要PM,建议是通过PMP认证的项目经理,主要负责项目各个过程的管理,以及过程优化降低开发风险。 3.系统架构师:架构师不单单是技术架构,还

    2022年4月10日
    139
  • kettle工具使用教程_iphone实用配置工具问题

    kettle工具使用教程_iphone实用配置工具问题kettle工具的使用

    2022年10月9日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号