当前位置:文档之家› 操作系统原理 进程通信共享内存

操作系统原理 进程通信共享内存

课程实践报告书课程名称:操作系统原理题目:进程通信-共享内存学生姓名:专业:计算机科学与技术(网络方向)班别:计科本113班学号:1104402308指导老师:日期:2013 年06 月25 日目录一、基本要求 (2)二、流程图分析 (3)三、共享内存描述和使用 (10)3.1共享内存的概述 (10)3.2共享内存的原理 (11)3.3共享内存的分配 (12)3.4 共享内存的访问 (13)3.5共享内存的应用 (13)3.6共享内存的意义 (14)四、实验构思 (14)4.1 main()的使用 (14)4.2 shmget()调用 (16)4.3 fork()的调用 (16)4.4 子进程调用shmat() (17)4.5子进程调用shmdt() (17)4.6 父进程调用 shmctl() (17)4.7父进程调用shmat(),shmdt(),shmctl() (18)五、实验的调试与测试 (18)六、实验结果 (20)七、源程序 (21)八、实验感受 (23)九、参考文献 (24)一、基本要求1.1实验题目:进程通信共享内存1.2实践目的:用代码实现进程通信共享内存1.3实践内容:用C语言代码创建进程,实现进程通信共享内存(父进程和子进程通过共享内存实现信息的交流)1.4实验环境:linux操作系统及gcc工具二、流程图分析图1-1如图1-1首先父进程调用shmget()函数建立一个共享内存,该函数返回一内存的标识符。

图1-2如图1-2父进程调用fork()产生一个子进程图1-3如图1-3子进程调用shmat()函数将该共享内存连接到自己的虚存空间中图1-4如图1-4写完数据后,子进程调用shmdt()函数断开与该进程的连接如图1-5如图1-5父进程调用shmctl()函数得到关于这块共享内存的相关信息,并打印出来图1-6如图1-6父进程调用shmat()函数将这块共享内存连接到自己的虚存空间图1-7如图1-8父进程调用shmdt()函数断开与该共享内存的连接图1-8如图1-8父进程调用shmctl()函数,销毁该共享进程。

三、共享内存描述和使用3.1共享内存的概述针对消息缓冲需要占用CPU进行消息复制的缺点,操作系统提供了一种进程间直接进行数据交换的通信方式——共享内存。

顾名思义,这种通信方式允许多个进程共享同一块物理内存空间来实现进程之间的信息交换,其特点是没有中间环节,直接将共享的内存页面通过附接,映射到相互通信的进程各自的虚拟地址空间中,从而使多个进程可以直接访问同一个物理内存页面,如同访问自己的私有空间一样(但实质上不是私有的而是共享的)。

因此这种进程间通信方式是在同一个计算机系统中的诸进程间实现通信的最快捷的方法,而它的局限性也在于此,即共享内存的诸进程必须共处同一个计算机系统,有物理内存可以共享才行。

3.2共享内存的原理共享内存是由IPC为一个进程所创建并且出现在这个进程的地址空间中的一段特殊的地址序列。

其他的进程可以将同样的共享内存段关联到他们自己的地址空间中。

所有的进程都可以访问这段内存地址,就如同这段内存是由malloc所分配的。

如果一个进程写入共享内存,这些改变立即就可以为访问相同共享内存的其他进程所见。

就其自身而言,共享内存并没有提供任何共享方法。

并没有自动的方法来阻止在第一个进程完成写入共享内存之前第二个进程开始读取共享内存。

3.3共享内存的分配要使用一块共享内存,进程必须首先分配它。

随后需要访问这个进程释放该共享内存块。

尽管每个进程都有自己的内存地址,不同的进程可以同时将同一个内存页面映射到自己的地址空间中,从而达到共享内存的目的。

分配一个新的共享内存块会创建新的内存页面。

因为所有进程都希望共享对同一块内存的访问,只应由一个进程创建一块新的共享内存。

再次分配一块已经存在的内存块不会创建新的页面,而只是会返回一个标识该内存块的标识符。

一个进程如需使用这个共享内存块,则首先需要将它绑定到自己的地址空间中。

这样会创建一个从进程本身虚拟地址到共享页面的映射关系。

当对共享内存的使用结束之后,这个映射关系将被删除。

当再也没有进程需要使用这个共享内存块的时候,必须有一个(且只能是一个)进程负责释放这个被共享的内存页面。

所有共享内存块的大小都必须是系统页面大小的整数倍。

系统页面大小指的是系统中单个内存页面包含的字节数。

进程通过调用shmget来分配一个共享内存块。

该函数的第二个参数指定了所申请的内存块的大小。

因为这些内存块是以页面为单位进行分配的,实际分配的内存块大小将被扩大到页面大小的整数倍。

3.4 共享内存的访问要让一个进程获取对一块共享内存的访问,这个进程必须先调用shmat(SHared Memory Attach,绑定到共享内存)。

将 shmget 返用于映射。

3.5共享内存的应用共享内存的通信方式是通过将可以共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的,因此,这些进程之间的读写操作的同步问题操作系统无法实现,必须由诸共享该内存的进程去控制。

另外,由于内存实体存在于计算机系统中,所以只能由处于同一个计算机系统中的诸进程共享。

以上两点是共享内存通信的缺点,但是它提供了诸进程直接读写信息,无须复制,因而方便快捷的进程间通信方式,适用于信息量大且操作频繁的场合。

3.6共享内存的意义或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回内容的时候,其它进程都会察觉到这个更改。

所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率。

访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成。

同时它也避免了对数据的各种不必要的复制。

四、实验构思4.1 main()的使用int main(){int shmid;char *shmaddr;strut shmid_ds buf;shmid=shmget(KEY,SIZE,IPC_CREAT | 0600);if(shmid==-1){printf("create share memory failed:%s",strerror(errno));return 0;}if(fork()==0){sleep(2);shmaddr=(char *)shmat(shmid,NULL,0);if(shmaddr==(void*)-1){printf("connect to the share memory failed:%s",strerror(errno));return 0;}strcpy(shmaddr,"hello,this is shared data.\n");shmdt(shmaddr);exit(0);}else{wait(0);shmctl(shmid,IPC_STAT,&buf);printf("size of the share memory:shm_segsz=%dbytes\n",buf.shm_segsz);printf("process id of the last operator:shm_lpid=%d\n",buf.shm_cpid);printf("process id of the last operator:shm_lpid+%d\n",buf.shm_lpid);shmaddr=(char *)shmat(shmid,NULL,0);if(shmaddr==(void *)-1){printf("connectthe share memoryfailed:%s",strerror(errno));return 0;}printf("print the content of the share memory:");printf("%s\n",shmaddr);shmdt(shmaddr);shmctl(shmid,IPC_RMID,NULL);}}4.2 shmget()调用首先调用shmget()函数建立一块共享内存,大小为1024个字节,shmid=shmget(KEY,SIZE,IPC_CREAT | 0600)建立共享内存,此函数调用用于创建一个新的共享内存段或存取一个已存在的共享内存段。

函数调用成功返回共享内存段的标识符,否则返回一1值。

s h mg e t的内部实现包含了许多重要的S y s t e m V共享内存机制;s h ma t 在把共享内存区域映射到进程空间时,并不真正改变进程的页表。

当进程第一次访问内存映射区域访问时,会因为没有物理页表的分配而导致一个缺页异常,然后内核再根据相应的存储管理机制为共享内存映射区域分配相应的页表。

4.3 fork()的调用调用fork()产生一个子进程(生产者进程)。

子进程调用shmat()函数将该共享内存连接(attach)到自己的虚存空间,即可通过普通的内存写操作(例如strcpy等),在该共享内存写入数据。

4.4 子进程调用shmat()shmaddr=(char *)shmat(shmid,NULL,0) 系统自动选择一个地址连接,s h ma t ( ) 可以创建一个共享内存区,或者获得已创建的共享内存区的标识符后,将共享内存段映射到进程的内存空间。

返回共享内存段的地址,否则返回一1值。

4.5子进程调用shmdt()写完数据生,子进程调用shmdt(shmaddr)断开共享,此函数调用可以将映射到进程的共享内存段撤消。

函数调用成功返回0值,否则返回一1 。

一个共享内存与一个进程分离时.共享内存段的s h m a r r a y结构中的共享计数减1 ,直至计数为0 ,系统才真正删除这个共亨内存页面。

4.6 父进程调用 shmctl()父进程sleep,直到子进程完成上述操作。

shmctl(shmid,IPC_RMID,NULL)取得共享内存的相关信息,并打印出来s h mct l 可以用来查询一些共享内存的使用情况和进行一些控制操作。

函数调用成功后返回0值,否则返回一1 值。

比如:s h mc t l ( s h m i d ,I P C RMI D,0 ) 将删除s h m i d指示的共享内存。

4.7父进程调用shmat(),shmdt(),shmctl()父进程调用shmat()函数将这块共享内存连接到自己的虚存空间,即可通过普通的内存读操作(例如printft等),将该共享内存中的字符串读出来。

读完数据后,父进程调用shmctl()函数,销毁断开与该共享内存的连接。

相关主题