当前位置: 首页 > news >正文

进程的共享主存通信实验

进程的共享主存通信

【预备知识】

共享存储区为进程提供了直接通过主存进行通信的有效手段,不像消息缓冲机制那样需要系统提供缓冲,也不像pipe机制那样需要事先建立一个特殊文件,而是由通信双方直接访问某些共享虚拟储存空间。在Linux中,系统管理一组共享主存段控制块。通信进程在使用共享主存段以前,首先提出申请,系统为之分配存储空间并返回共享主存段标识号。一个共享段建立后,进程把它被附加到自己虚拟空间中。一个进程可以附加多个共享主存段。一个共享主存段一旦被附加到进程的虚拟空间后,对它的访问与其他虚拟地址的访问完全相同。但为了保证共享主存段数据的完整性,通信的进程之间要互斥地进行访问。当通信进程不再需要该共享主存段时,可使用命令将其与进程分离,从而使其从进程的虚空间删除。

  1. 共享主存段使用的数据结构

(1)共享主存段控制块(或共享主存段头)

每个共享主存段都有一个控制块,用来描述共享主存段的一些属性,共享主存段控制块定义在sys/shm.h中,其结构如下:

struct shmid_ds

{

struct ipc_perm shmperm;         / * 共享主存段访问控制结构 * /

int shmsegsz;                    / * 共享段以字节为单位的长度 * /

struct ptentry * shmptbl;        / * 共享页表始址 * /

ushort shmlpid;                  / * 最近执行共享段操作的进程标识 * /

ushort shmcpid;                  / * 创建共享段的进程标识 * /

ushort shmnattch;                / * 当前附件段号 * /

ushort shmcnattch;               / * 主存中的附加段号 * /

time_t shmatime;                 / * 最近一次附件操作的时间 * /

time_t shmdtime;                 / * 最近一次与进程分离操作的时间 * /

time_t shmctime;                 / * 最近一次修改时间 * /

}

为了便于管理,系统将维持的共享主存段组成一个表,共有SHMMNI=100个元素,其结构如下:

struct shmid_ds shmen[SHMMNI];   / * 共享段表 * /

其访问控制结构定义如下:

struct ipc_perm

   key_t key;

   ushort uid;              /* owner euid and egid * /

   ushort gid;

   ushort cuid;

  ushort cgid;

  ushort mode; /*lower 9 bits of shmflg*/

  ushort seq   /*sequence number*/

};

(2)共享主存段的数据结构

每个共享主存段都对应一个页表和允许的存取权限,结构如下;

struct shmptds

{

int shmspte;  /*开始也表项*/

int shmsflg;  /*对共享段的读/写权限*/

}

每个进程最多允许6个共享主存段(SHMSEG=6).

  1. 申请一个共享主存段

参与通信的进程,通信前要先申请一个共享主存段,若是第一次申请,则要为其分配一个主存空间及页表,并对共享主存区控制块进行初始化,申请共享主存段调用语法如下:

# include<sys/ipc.h>

# include<sys/shm.h>

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

其中,key为共享主存段的关键字,size是共享主存段字节长度,shmflg为创建和访问标志。

返回值:成功时,为与key值相关的共享主存段的标识号,且大小是页对齐;失败时,为-1。

如果key的值为IPC_PRIVATE,或不为IPC_PRIVATE,创建的共享段与key无关,关键字由系统分配。

Shmflg由如下成分组成:

.IPC_CREAT,创建一个新段。如果该标志没有设置,将查找与key相关的段,且该段允许用户访问。

.IPC_EXCL,与IPC_CREAT一起使用,确保创建一个新的共享段。若该段已经存在,出错。

低9位为三类用户的访问方式的定义。

  1. 将共享段附加到申请通信的进程空间

对于已申请通信所需的共享段,进程需把它附加到自己的虚拟空间后才能对其进行读写,将共享段附加到申请通信的进程空间的函数调用语法:

#include < sys/sem.h >

void shmat ( int shmid,coid * shmadd,nt shmflg);

这里shmid是进程调用shmget后返回的共享段标识号;shmadd是给出的应附加到进程虚空间的地址;shmflg为允许对共享段的访问方式。

返回值:成功时为附加到进程地址空间的虚地址,失败时为-1。

连接到进程虚空间的地址规则为:

.shmadd为0,则将该共享段附加到系统选择的进程的第一个可用地址之后。

.shmadd为非0,如果shmflg指定了SHM_RND标志,则将该共享段附加shmadd取整后指定的地址上。

.shmadd为非0,如果shmflg未指定SHM_RND标志,则将该共享段附加shmadd指定的地址上。通常将shmadd指定为0,由系统安排连接地址。

4.将共享段与进程之间解除链接

当进程不再需要共享段时,将其从它的地址空间拆下,调用语法为:

#include < sys/sem.h >

int shmdt( void * shmaddr );

其中,shmaddr是共享段在进程地址空间的虚地址。返回值为0。

5.对共享段进行控制

#include < sys/sem.h >

int shmctl(int shmid,int cmd,struct_ds * buf);

返回值:成功时为0,失败时为-1。

系统调用shmctl根据控制命令cmd对共享段进行控制。cmd可能的取值有:

. IPC_STAT,将有关共享段的信息复制到具有shmid_ds结构的buf中;

. IPC_SET,用于用户和用户组,或对其存取权限进行修改,要求用户必须为超级用户或拥有者;

. IPC_RMID,用于标志删除共享段。在共享段与所有进行分离时,实际进行删除;

. IPC_LOCK,在Linux环境下,将共享段锁在主存中;

. IPC_UNLOCK,在Linux环境下,允许将共享段锁换出主存。

编程实现例<一>

【任务】

编程实现一个是进程向共享段写信息的例子。

【程序】

#include  <sys/types.h>#include  <sys/ipc.h>#include  <sys/shm.h>#define SHMKEY 75#define  K  1024int shmid;main(){int i,*pint;char *addr;extern char *shmat();shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);/*申请创建一个16K大小的共享存储段,其标识号为SHMKEY*/addr=shmat(shmid,0,0);   /*缺省地址将共享段附加到系统指定位置*/printf(“addr ox%x\n”,addr);/*打印附加到进程地址空间的地址*/pint=(int *) addr;for (i=0;i<256;i++)*pint++=i;           /*向共享主存段写入0~255个数*/pint=(int *)addr;*pint=256;          /*共享段第一个字中写入信息长度256,以便接收进程读*/Pause();           /*暂停等待接收进程读*/}

修正后的代码:

【运行结果】

【分析】

第一个例子是一个进程向共享段写信息的例子,它使用了共享内存来实现进程间的通信。程序首先申请创建一个16K大小的共享存储段,标识号为SHMKEY,然后将共享段附加到系统指定位置,并打印附加到进程地址空间的地址。接着向共享主存段写入0~255个数,并在共享段第一个字中写入信息长度256,以便接收进程读取。最后暂停等待接收进程读

编程实现例<二>

【任务】

编程实现从共享段读信息的例子

【程序】

#include  <sys/types.h>#include  <sys/ipc.h>#include  <sys/shm.h>#define SHMKEY 75#define  K  1024int shmid;main(){int i,*pint;char *addr;extern char *shmat();shmid=shmget(SHMKEY,8*K,0777);  /*由SHMKEY得到共享段标识号*/addr=shmat(shmid,0,0);   /*将共享段与本进程相连*/pint=(int *) addr;while (*pint==0);       /*若共享区无信息时,在此等待*/for (i=0;i<256;i++)printf(“%d\n”,*pint++);}
修正后的代码:

【运行结果】

【分析】

第二个例子是一个从共享段读信息的例子,同样使用了共享内存来实现进程间的通信。程序首先通过SHMKEY得到共享段标识号,然后将共享段与本进程相连。接着程序进入一个while循环,在共享区无信息时,在此等待。当共享区有信息时,将信息读取出来并打印出来。

http://www.lryc.cn/news/347575.html

相关文章:

  • 深度缓冲技术在AI去衣中的神奇作用
  • 能效?性能?一个关于Windows下使用openssl speed进行速度测试的诡异问题
  • block性能考虑和线程安全
  • 没有公网ip,如何实现外网访问内网?
  • Python中如何将小数转化为百分数进行输出
  • 加入全球少儿编程运动:Scratch让每个孩子都能成为创造者(Scratch最新版客户端和初/中/高级学习资料整理分享)
  • 引擎:主程渲染
  • Java 高级面试问题及答案
  • 邮件的安全认证(dkim/spf/dmarc)
  • 单调栈问题
  • Hexo博客重新部署与Git配置
  • KUKA机器人专业名词解释
  • 阿里云 物联网平台 MQTT连接、数据传输
  • 栈和队列OJ练习题及解答
  • 渗透测试-信息收集
  • 电力乙级资质延伸换证:企业转型的契机
  • 基于Redis实现分布式锁——Java版本
  • Qt自定义控件--提升为
  • Lua 基础 01 入门
  • 远程连接阿里云ECS
  • 【C++】多态(上)超详细
  • 【Git】 Git分支操作指南
  • 智慧文旅赋能旅游服务升级:以科技创新驱动行业变革,打造智慧化、个性化、高效化的旅游新体验,满足游客日益增长的多元化需求
  • AtCoder Beginner Contest 310 E题 NAND repeatedly
  • 一款简易的免费抽奖软件
  • Kubernetes 监控管理
  • 哈希表第6/9题--四数相加II
  • 使用JavaScript将富文本HTML转换为纯文本
  • 2024-05-13 问AI: 介绍一下 google wavenet 声码器
  • 当代 Qt 正确的 安装方法 及 多版本切换