《操作系统》课程实验二

该内存不能为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类似,也可以为当前执行的每个程序维护一个消息队列.
线程将消息放入程序的消息队列中.
消息队列可以看做用于存储消息的区域,不同的进程(线程)可以将消息放入消息队列或者从消息队列中取出消息.

TNAHosting($5/月)4核/12GB/500GB/15TB/芝加哥机房

TNAHosting是一家成立于2012年的国外主机商,提供VPS主机及独立服务器租用等业务,其中VPS主机基于OpenVZ和KVM架构,数据中心在美国芝加哥机房。目前,商家在LET推出芝加哥机房大硬盘高配VPS套餐,再次刷新了价格底线,基于OpenVZ架构,12GB内存,500GB大硬盘,支持月付仅5美元起。下面列出这款VPS主机配置信息。CPU:4 cores内存:12GB硬盘:500GB月流...

hostkvm:7折优惠-香港VPS韩国VPS,8折优惠-日本软银、美国CN2 GIA、新加坡直连VPS

hostkvm本月对香港国际线路的VPS、韩国CN2+bgp线路的VPS正在做7折终身优惠,对日本软银线路、美国CN2 GIA线路、新加坡直连线路的VPS进行8折终身优惠促销。所有VPS从4G内存开始支持Windows系统,当然主流Linux发行版是绝对不会缺席的!官方网站:https://hostkvm.com香港国际线路、韩国,7折优惠码:2021summer日本、美国、新加坡,8折优惠码:2...

易探云服务器怎么过户/转让?云服务器PUSH实操步骤

易探云服务器怎么过户/转让?易探云支持云服务器PUSH功能,该功能可将云服务器过户给指定用户。可带价PUSH,收到PUSH请求的用户在接收云服务器的同时,系统会扣除接收方的款项,同时扣除相关手续费,然后将款项打到发送方的账户下。易探云“PUSH服务器”的这一功能,可以让用户将闲置云服务器转让给更多需要购买的用户!易探云服务器怎么过户/PUSH?1.PUSH双方必须为认证用户:2.买家未接收前,卖家...

该内存不能为read是什么意思为你推荐
云主机租用租用云主机有什么好处?虚拟主机代理谁给推荐个好的虚拟主机无限级代理中国域名注册中国十大域名注册商域名购买如何购买域名?香港虚拟空间香港虚拟空间哪家好?合肥虚拟主机虚拟主机是干嘛的?买了虚拟主机是否要一台电脑?山东虚拟主机能否在虚拟机与主机之间建立局域网,让主机与虚拟机同时上网?青岛虚拟主机阿里云主机青岛好还是杭州好双线虚拟主机双线虚拟主机是智能的吗www二级域名www的域名是一级域名还是二级域名
网通服务器租用 动态ip的vps 免费com域名申请 siteground 老左博客 日志分析软件 godaddy优惠券 双11抢红包攻略 天猫双十一抢红包 魔兽世界台湾服务器 好看qq空间 qq数据库下载 亚马逊香港官网 免费cdn 鲁诺 服务器监测 香港亚马逊 中国电信网络测速 游戏服务器出租 美国迈阿密 更多