《操作系统》课程实验二

该内存不能为read是什么意思  时间:2021-01-19  阅读:()

实验报告高级进程间通信问题班级:无47姓名:刘前1学号:2014011216日期:2016年11月25日操作平台:Windows8.
1编程语言:C++1清华大学电子工程系(E-mail:liuqian14@mails.
tsinghua.
edu.
cn)《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前2高级进程间通信问题实验目的:1.
通过对进程间高级通信问题的编程实现,加深理解进程间高级通信的原理;2.
对Windows或Linux涉及的几种高级进程间通信机制有更进一步的了解;3.
熟悉Windows或Linux中定义的与高级进程间通信有关的函数.
实验题目:本实验共有2个实验题目,任选其中之一.
不同实验的难度不同,基准分也不同,请同学根据自己的情况加以选择.
实验题目基准分二元自然数变量函数计算问题90快速排序问题100操作系统平台可选Windows或Linux,编程语言不限.
实验报告内容要求:1.
写出设计思路和程序结构,并对主要代码进行分析;2.
实际程序运行情况;3.
对提出的问题进行解答;4.
体会或者是遇到的问题.
注:本人在实验二中选择的是二元自然数变量函数计算问题.
《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前3二元自然数变量函数计算问题一、问题描述及实验要求1.
问题描述:设有二元自然数变量函数,其中请编程建立3个并发协作进程或线程,分别完成计算、和.
2.
实验步骤(a)首先创建三个线程(或进程),分别执行函数、和计算;(b)线程(或进程)之间的通信可以选择下述机制之一进行:管道(无名管道或命名管道)消息队列共享内存(c)通过适当的函数调用创建上述IPC对象,通过调用适当的函数调用实现数据的读出与写入;(d)需要考虑线程(或进程)间的同步;(e)线程(或进程)运行结束,通过适当的系统调用结束线程(或进程).
3.
实验平台和编程语言:自由选择Windows或Linux.
编程语言不限.
4.
思考题1.
你采用了你选择的机制而不是另外的两种机制解决该问题,请解释你做出这种选择的理由.
2.
你认为另外的两种机制是否同样可以解决该问题如果可以请给出你的思路;如果不能,请解释理由.
《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前4二、设计思路首先对二元自然数变量函数计算问题进行分析.
函数f(m)的功能是计算输入自然数m的阶乘;函数g(n)的功能是计算输入自然数n对应的斐波那契数;函数F将函数f和g的计算结果相加.
通过分析可以看出,如果不要求使用高级进程间通信,即使是编程初学者,也能在很短的时间内完成这一问题,但是本次实验要求使用高级进程间通信解决这一问题,因而需要IPC机制来实现进程(线程)之间的通信.
IPC机制要求对三个函数建立各自的线程,函数间参数或数值结果的传递采用消息队列、共享内存或管道等高级进程间通信进制来实现.
本人采用匿名管道的方式实现进程间通信.
根据问题要求,本问题需要两个匿名管道,一个管道实现函数f和F之间的通信,另一个管道实现g和F之间的通信,为方便下文表述将两个管道分别称为管道A、B.
每个管道在被创建时都会生成两个句柄,分别为管道的读句柄和写句柄,分别与WriteFile和ReadFile函数协同实现向管道的写入和读取.
使用匿名管道机制解决本问题的主要思路是:1.
主函数main()输入两个自然数,分别为函数f的参数m和g的参数n;2.
将m写入管道A,n写入管道B;3.
f函数从管道A中读取已经被写入的m,经过计算得到结果f(m),并将结果写回管道A;4.
g函数从管道B中读取已经被写入的n,经过计算得到结果g(n),并将结果写回管道B;5.
F函数从管道A和B中分别读取f(m)和g(n),相加得到最后结果;6.
将函数F的最后结果输出.
综合以上分析,可以看出,本实验的思路非常清晰,关键是如何使用Windows中管道机制的函数实现以上过程.
三、程序结构1.
基本数据结构及函数:本次程序比较简单,没有使用特殊的数据结构,主要涉及的变量包括管道的读写句柄、线程的句柄,以及管道机制和线程中常用的函数.
程序中具体使用的变量和函数及其说明如下:《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前5变量说明HANDLEHREAD_fFf和F之间的管道读句柄HANDLEHWRITE_fFf和F之间的管道写句柄HANDLEHREAD_gFg和F之间的管道读句柄HANDLEHWRITE_gFg和F之间的管道写句柄HANDLEf_threadf函数对应的线程HANDLEg_threadg函数对应的线程HANDLEF_threadF函数对应的线程自己编写的函数及说明如下:函数说明intf(intm)函数f(m)intg(intn)函数g(n)voidWINAPIf_PIPE_RW(PVOIDpvParam)f函数向管道的读写操作voidWINAPIg_PIPE_RW(PVOIDpvParam)g函数向管道的读写操作voidWINAPIF_PIPE_RW(PVOIDpvParam)F函数向管道的读写操作Windows.
h中对管道的操作函数:与管道相关的函数函数说明CreatePipe()创建管道ReadFile()读取数据WriteFile()写入数据CloseHandle()关闭管道Windows.
h中对线程的操作函数:与线程的相关函数函数说明CreateThread()创建线程CloseHandle()关闭线程WaitForSingleObject()等待进程结束2.
实现方法:首先,使用递归方法实现函数f和函数g.
函数f(m)的功能是求m的阶乘,而函数g(n)的功能是求第n个斐波那契数.
然后创建三个线程,f、g和F三个函数分别对应线程f_thread,g_thread和F_thread.
《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前6对于f的线程f_thread,调用的函数为f_PIPE_RW,该函数实现从管道A中读取参数m,进行运算后将结果写回管道A;对于g的线程g_thread,调用的函数为g_PIPE_RW,该函数实现从管道B中读取参数n,进行运算后将结果写回管道B;对于F的线程F_thread,调用的函数为F_PIPE_RW,该函数是本程序的核心函数,一开始向管道写入函数f和g各自的参数,最后从管道读取两个函数的返回值,相加得到最终结果,输出到控制台窗口.
因此,程序中核心的操作由函数F_PIPE_RW完成,通过在主函数建立调用线程F_thread即可实现.
当线程F_thread结束时,函数F(m,n)的结果已经输出.
3.
对程序结构的解释:上图清楚展示了本程序的结构图,但没有对线程进行解说明,现补充如下:程序中,main()创建线程F_thread,该线程调用了F_PIPE_RW函数.
F_PIPE_RW函数是程序的核心函数,问题解决的过程由该函数实现.
F_PIPE_RWf_PIPE_RW管道A管道B将函数f的参数m写入管道将函数g的参数n写入管道计算f(m)计算g(n)控制台窗口输入函数f、g的参数m和n输出F(m,n)的结果g_PIPE_RW将g(n)写入管道将f(m)写入管道《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前7首先,F_PIPE_RW从主函数main()中接收到输入的两个自然数,接着建立起两个管道A和B,分别实现f与F之间的通信和g与F之间的通信.
管道建立成功后,将m写管道A,将n写入管道B.
再建立两个线程f_thread和g_thread,分别实现f函数和g函数从管道读取数据、处理并将结果写回对应的管道.
使用两个WaitForSingleObject()函数分别等待两个线程的结束.
两线程结束表明已经将函数结果写回管道,此时再分别从管道中读取f(m)和g(n),两者相加输出F(m,n)=f(m)+g(n)结果即可.
四、代码分析1.
全局变量:程序中定义的全局变量有:DWORDnum_of_bytes=sizeof(int);HANDLEHREAD_fF;//f和F之间的管道读句柄HANDLEHWRITE_fF;//f和F之间的管道写句柄HANDLEHREAD_gF;//g和F之间的管道读句柄HANDLEHWRITE_gF;//g和F之间的管道写句柄其中DWORDnum_of_bytes作为管道的ReadFile和WriteFile函数的参数,表示写入或读取数据的字节数.
因为本程序中每次写入或读取的数均为一个int型变量,因而定义num_of_bytes=sizeof(int).
两个管道的读写句柄也用全局变量,是为了减少函数之间传递参数造成不必要的麻烦.
2.
函数f(m)和g(n)根据函数的表达式,使用递归的思想即可实现两个函数.
//f函数(功能是计算阶乘)intFunc_f(intm){if(m==1)return1;elsereturn(m*Func_f(m-1));}//g函数(斐波那契数列)intFunc_g(intn){if(n==1||n==2)return1;elsereturn(Func_g(n-1)+Func_g(n-2));}《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前83.
f_PIPE_RW函数f_PIPE_RW函数实现了从管道中读取参数m,经过运算再将结果写入管道.
对f来说,f向F传递数据相当于向管道写入数据;f从F得到数据相当于从管道读入数据.
voidWINAPIf_PIPE_RW(PVOIDpvParam)//实现f函数从管道读取和向管道写入数据{DWORDread_dword,write_dword;//返回实际读取或写入的字节数intpara_m;//管道内的数据,即为参数mwhile(!
ReadFile(HREAD_fF,¶_m,num_of_bytes,&read_dword,NULL));//从管道中读取参数m,使用while表示等待数据直到成功读入intf_result=Func_f(para_m);//对读取的参数m使用f函数,得到结果while(!
WriteFile(HWRITE_fF,&f_result,num_of_bytes,&write_dword,NULL));//将f函数的结果写入管道,使用while表示直到成功写入}4.
g_PIPE_RW函数g_PIPE_RW函数实现了从管道中读取参数m,经过运算再将结果写入管道.
对g来说,g向F传递数据相当于向管道写入数据;g从F得到数据相当于从管道读入数据.
voidWINAPIg_PIPE_RW(PVOIDpvParam)//实现g函数从管道读取和向管道写入数据{DWORDread_dword,write_dword;//返回实际读取或写入的字节数intpara_n;//管道内的数据,即为参数nwhile(!
ReadFile(HREAD_gF,¶_n,num_of_bytes,&read_dword,NULL));//从管道中读取参数n,使用while表示等待数据直到成功读入intg_result=Func_g(para_n);//对读取的参数n使用g函数,得到结果while(!
WriteFile(HWRITE_gF,&g_result,num_of_bytes,&write_dword,NULL));//将g函数的结果写入管道,使用while表示直到成功写入}5.
F_PIPE_PW函数F_PIPE_RW函数是程序的核心函数,实现了问题完整的求解过程.
《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前9a)创建两个管道:其中安全性参数的设置参照了课件上的代码.
//安全性参数设置SECURITY_ATTRIBUTESsafF,sagF;//对应于两个管道的安全性//安全性的参数设置,建立f和F之间的管道safF.
nLength=sizeof(SECURITY_ATTRIBUTES);safF.
lpSecurityDescriptor=NULL;safF.
bInheritHandle=TRUE;CreatePipe(&HREAD_fF,&HWRITE_fF,&safF,0);//安全性的参数设置,建立g和F之间的管道sagF.
nLength=sizeof(SECURITY_ATTRIBUTES);sagF.
lpSecurityDescriptor=NULL;sagF.
bInheritHandle=TRUE;CreatePipe(&HREAD_gF,&HWRITE_gF,&sagF,0);b)将输入的m和n写入对应的管道:核心是使用WriteFile()函数将sizeof(int)字节数的数据写入管道中.
//将输入的两个参数写入管道intm=para[0];intn=para[1];DWORDdword_fF,dword_gF;//返回实际读入的字节数while(!
WriteFile(HWRITE_fF,&m,num_of_bytes,&dword_fF,NULL));//F函数向管道写入f函数的参数mwhile(!
WriteFile(HWRITE_gF,&n,num_of_bytes,&dword_gF,NULL));//F函数向管道写入g函数的参数nc)两个线程分别计算f(m)和g(n):使用WaitForSingleObject()函数等待线程结束.
HANDLEf_thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(f_PIPE_RW),NULL,0,NULL);//建立f函数读写的线程HANDLEg_thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(g_PIPE_RW),NULL,0,NULL);//建立g函数读写的线程WaitForSingleObject(f_thread,INFINITE);//f_thread线程结束时,f(m)已写入管道WaitForSingleObject(g_thread,INFINITE);//g_thread线程结束时,g(n)已写入管道《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前10d)读取管道中返回的计算结果,输出最后结果:intf_result,g_result;//分别表示f函数和g函数的返回值while(!
ReadFile(HREAD_fF,&f_result,num_of_bytes,&dword_fF,NULL));//F函数从管道中读取f函数的返回值while(!
ReadFile(HREAD_gF,&g_result,num_of_bytes,&dword_gF,NULL));//F函数从管道中读取g函数的返回值intF_result=f_result+g_result;//F(m,n)=f(m)+g(n)cout<主函数建立F_PIPE_RW函数对应的线程:HANDLEF_thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(F_PIPE_RW),¶,0,NULL);WaitForSingleObject(F_thread,INFINITE);//F函数的线程结束时,已经输出了函数返回值CloseHandle(F_thread);//关闭线程句柄以上代码通过管道实现了三个进程间的通信,最后的输出即为F(m,n)的计算结果.
五、程序运行结果:以下通过若干例子测试程序的正确性.
1.
m=2,n=3程序运行结果:********请输入两个自然数m和n********23输出结果*F(2,3)=4请按任意键继续.
.
.
《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前11验证:f(m)=f(2)=2!
=2;g(n)=g(3)=1+1=2;F(m,n)=F(2,3)=2+2=4.
验证结果正确.
2.
m=10,n=8程序运行结果:********请输入两个自然数m和n********108输出结果*F(10,8)=3628821请按任意键继续.
.
.
验证:f(m)=f(10)=10!
=3628800;g(n)=g(8)=21;F(m,n)=F(10,8)=3628800+21=3628821.
验证结果正确.
同样,测试的其他例子都证明程序是正确的.
3.
另外,程序还设置了简单的输入合法性判断,当m,n输入为00时,程序运行结果为:********请输入两个自然数m和n********00Error:输入有误!
请输入两个自然数!
请按任意键继续.
.
.
总之,程序的运行结果是正确的.
六、思考题1.
你采用了你选择的机制而不是另外的两种机制解决该问题,请解释你做出这种选择的理由.
答:本实验提供了三种可选的高级进程间通信机制,分别为消息队列、共享内存和管道.
之所以选择管道机制主要有以下原因:《操作系统》课程实验二:高级进程间通信问题二元自然数变量函数计算问题2014011216刘前12a)操作系统课程讲解了Linux系统下消息队列的实现方法,但是没有具体讲解Windows如何实现,因为我选择的是Windows操作系统,所以首先不选择消息队列机制;b)共享内存和管道的思路都比较清晰简单,但是共享内存对内存的映射、清理等感觉有些复杂,而管道的操作比较简单,很容易按照思路一步步实现;c)课件中只列出了共享内存常用的一些函数,但是没有给出具体的实现方法,因而还需要查阅一些课外资料;而对管道机制的具体实现则举了实例,理解了之后感觉实现起来比较简单,其中程序中关于安全性部分的参数就是参照了课件上的内容;管道机制分为两种,包括匿名管道和命名管道.
匿名管道比命名管道需要更少的开销,但是提供有限的服务,由于本题只需要来回一次数据的传递,因而对管道服务的要求不高,所以采用了容易实现、开销少的匿名管道.
2.
你认为另外的两种机制是否同样可以解决该问题如果可以请给出你的思路;如果不能,请解释理由.
答:除去管道之外,消息队列和共享内存机制同样可以解决进程(线程)间通信的问题.
a)消息队列机制:Windows操作系统下与Linux类似,也可以为当前执行的每个程序维护一个消息队列.
线程将消息放入程序的消息队列中.
消息队列可以看做用于存储消息的区域,不同的进程(线程)可以将消息放入消息队列或者从消息队列中取出消息.

优林云(53元)哈尔滨电信2核2G

优林怎么样?优林好不好?优林 是一家国人VPS主机商,成立于2016年,主营国内外服务器产品。云服务器基于hyper-v和kvm虚拟架构,国内速度还不错。今天优林给我们带来促销的是国内东北地区哈尔滨云服务器!全部是独享带宽!首月5折 续费5折续费!地区CPU内存硬盘带宽价格购买哈尔滨电信2核2G50G1M53元直达链接哈尔滨电信4核4G50G1M83元直达链接哈尔滨电信8核8G50G1M131元直...

百星数据(60元/月,600元/年)日本/韩国/香港cn2 gia云服务器,2核2G/40G/5M带宽

百星数据(baixidc),2012年开始运作至今,主要提供境外自营云服务器和独立服务器出租业务,根据网络线路的不同划分为:美国cera 9929、美国cn2 gia、香港cn2 gia、韩国cn2 gia、日本cn2 gia等云服务器及物理服务器业务。目前,百星数据 推出的日本、韩国、香港cn2 gia云服务器,2核2G/40G/5M带宽低至60元/月,600元/年。百星数据优惠码:优惠码:30...

EtherNetservers年付仅10美元,美国洛杉矶VPS/1核512M内存10GB硬盘1Gpbs端口月流量500GB/2个IP

EtherNetservers是一家成立于2013年的英国主机商,提供基于OpenVZ和KVM架构的VPS,数据中心包括美国洛杉矶、新泽西和杰克逊维尔,商家支持使用PayPal、支付宝等付款方式,提供 60 天退款保证,这在IDC行业来说很少见,也可见商家对自家产品很有信心。有需要便宜VPS、多IP VPS的朋友可以关注一下。优惠码SUMMER-VPS-15 (终身 15% 的折扣)SUMMER-...

该内存不能为read是什么意思为你推荐
免费虚拟主机空间请问哪里有:免费一级域名申请,免费虚拟主机,免费空间租服务器我想租服务器,请问会提供哪些服务?已备案域名查询如何快速查询已备案域名并抢注国外空间租用好用的国外空间php虚拟空间虚拟空间怎么修改php.ini配置网站空间价格1M网站空间是多少钱网站空间免备案哪里能找到免费、免备案的空间?北京虚拟主机租用租用虚拟主机在哪里租用比较好虚拟主机试用30天虚拟主机返佣是怎么回事?广西虚拟主机虚拟机如何实现桥接方式-联网
济南域名注册 天津服务器租赁 已经备案域名 阿里云os 便宜服务器 电影服务器 godaddy优惠码 搜狗12306抢票助手 南昌服务器托管 申请个人网页 华为4核 合肥鹏博士 个人域名 北京双线 宏讯 百度云加速 东莞服务器托管 photobucket 阿里云手机官网 徐州电信 更多