操作系统.docx
- 文档编号:5942595
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:23
- 大小:67.47KB
操作系统.docx
《操作系统.docx》由会员分享,可在线阅读,更多相关《操作系统.docx(23页珍藏版)》请在冰豆网上搜索。
操作系统
院系:
计算机科学学院___
专业:
自动化
年级:
2008
课程名称:
操作系统
指导教师:
__刘晶
组号:
组员:
姓名(学号)
姓名(学号)
姓名(学号)
年月日
实验1
简单进程通信
实
验
内
容
管道是进程间通信的一个基本途径,进程可以通过管道进行信息传输;管道就像它的名字一样,数据从它的一头流向另一头(当然有的情况也可以从另一头流向这一头)。
本次试验我们要做的试验内容主要有两点:
●1熟悉什么是管道,了解Unix/Linux支持的管道通信方式
●2读懂TXT文本上面的程序
●3能够自己编写用管道通行的程序实现管道间的进程通信
实
验
要
求
1用系统调用pipe()建立一个管道,两个子进程分别向管道各写一句话Child1issendingamessage!
, Child2issendingamessage!
父进程从管道中读出来自两个子进程的信息并显示。
2要求在子进程没有完全完成输入任务是父进程不得输出,只有子进程完全将信息输入到管道后,父进程才能将管道里面的信息输出。
3父进程显示管道里面的信息的时候应该先显示进程1的信息,然后再显示进程2的信息
小组成员
姓名
学号
组内分工
教师评分
小
组
成
绩
评
定
教师签名:
年月日
实
验
原
理
步
骤
(
算
法
流
程
)
#include
main()
{
inti,r,p1,p2,fd[2];
charbuf[50],s[50];/*两个缓冲,分别入管道和出管道*/
pipe(fd);/*父进程建立管道*/
while(p1=fork()==-1);/*创建子进程,此处中断,子进程为父进程副本*/
if(p1==0)/*说明此时处于子进程*/
{
lockf(fd[1],1,0);/*加锁锁定写入端*/
sprintf(buf,"childprocessp1issendingmessage!
\n");
printf("childprocessp1!
\n");
write(fd[1],buf,50);/*把buf中的字符写入管道*/
sleep(5);
lockf(fd[1],0,0);/*释放管道写端*/
exit(0);
}
else/*说明此时处于父进程*/
{
while(p2=fork()==-1);/*创建另外一个子进程*/
if(p2==0)
{
lockf(fd[1],1,0);
sprintf(buf,"childprocessp2issendingmessage!
\n");
printf("childprocessp2!
\n");
write(fd[1],buf,50);
lockf(fd[1],0,0);
exit(0);
}
wait(0);/*父进程阻塞自己,直到子进程完成*/
if(r=read(fd[0],s,50==-1))
printf("can'treadpipe\n");
elseprintf("%s\n",s);
exit(0);
}
}
实
验
结
果
及
分
析
实验结果:
实验结果是输出BUF中的内容,先输出的子进程1的内容,后输出子进程2的内容。
正确的事业结果的建立在正确的实验步骤上面,对于实验的结果。
我感觉的很正常
结果分析:
我通过学习管道的知识又懂得了:
管道与标准输入输出联合使用往往可以写出具有简单易用的多进合作应用,典型的应用是协同进程(或过滤进程)。
管道只能被两个进程使用,一个写,一个读;如何一个管道有多个进程写或多个进程读,之后的读写函数将失败,并设置相应的errno。
当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。
注:
(PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。
Posix.1要求PIPE_BUF至少为512字节,redhat7.2中为4096)
心
得
体
会
通过管道的进程通信实验我懂得了:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
一个进程向管道中写的内容被管道另一端的进程读出。
写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
实验3.1
进程同步与互斥(生产者消费者问题)
实
验
内
容
以生产者/消费者模型为依据,在Windows2000环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
实
验
要
求
●学习并理解生产者/消费者模型及其同步/互斥规则;
●学习了解Windows同步对象及其特性;
●熟悉实验环境,掌握相关API的使用方法;
●设计程序,实现生产者/消费者进程(线程)的同步与互斥;
●提交实验报告。
小组成员
姓名
学号
组内分工
教师评分
组
成
绩
评
定
教师签
年月日
实
验
原
理
步
骤
(
算
法
流
程
)
生产者进程(进程由多个线程组成)生产信息,例如它可以是计算进程。
消费者进程使用信息,它可以是输出打印进程。
由于生产者和消费者彼此独立,且运行速度不确定,所以很可能出现生产者已产生了信息而消费者却没有来得及接受信息这种情况。
为此,需要引入由一个或者若干个存储单元组成的临时存储区,以便存放生产者所产生的信息,平滑进程间由于速度不确定所带来的问题。
如果想使生产者进程和消费者进程协调合作,则必须使它们
遵循如下规则:
1)只要缓冲区有存储单元,生产者都可往其中存放信息;当缓冲区已满时,若任意生产者提出写要求,则都必须等待;
2)只要缓冲区中有消息可取,消费者都可从缓冲区中取出消息;当缓冲区为空时,若任意消费者想取出信息,则必须等待;
生产者流程图:
否
是
否
是
消费者流程图:
是
否
控制台代码:
#include
#pragmahdrstop
#pragmaargsused
#include"iostream.h"
/*
HANDLECreateSemaphore(
LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,//pointertosecurityattributes
LONGlInitialCount,//initialcount
LONGlMaximumCount,//maximumcount
LPCTSTRlpName//pointertosemaphore-objectname
);
*/
intmain(intargc,char*argv[])
{
HANDLEhSemEmptyBuffer;
HANDLEhSemFullBuffer;
hSemEmptyBuffer=CreateSemaphore(NULL,3,3,"EmptyBuff");
hSemFullBuffer=CreateSemaphore(NULL,0,3,"FullBuff");
cout<<"SemEmptyBufferandSemFullBufferOK."< cin.get(); CloseHandle(hSemEmptyBuffer); CloseHandle(hSemFullBuffer); cout<<"SemEmptyBufferandSemFullBufferOver."< cin.get(); return0; } 这一段代码的主要功能是对信号量的设置,此处设置了两个信号量: hSemEmptyBuffer和hSemFullBuffer,并给他们以初始值,分别为3和0,同时设置了缓冲区的长度为3,意思为起始状态缓冲区为空,并且一次最多可以生产三个物品。 这两个信号量是保证生产者和消费者同步和互斥必不可少的条件。 生产者代码: #include #pragmahdrstop #pragmaargsused #include"iostream.h" intmain(intargc,char*argv[]) { HANDLEhSemEmptyBuffer; HANDLEhSemFullBuffer; longintiFullBuffer=0; hSemEmptyBuffer=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EmptyBuff"); hSemFullBuffer=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FullBuff"); cout<<"正在生产物品。 。 。 。 "< cin.get(); cout<<"试图放入物品"< cin.get(); WaitForSingleObject(hSemEmptyBuffer,INFINITE); /*************************************/ /**************互斥P******************/ /************具体操作*****************/ /**************互斥V******************/ /*************************************/ cout<<"成功放入物品,并准备通告"< cin.get(); ReleaseSemaphore(hSemFullBuffer,1,&iFullBuffer); cout<<"新生产了一个产品,之前共有"< cout<<"通告完毕,退出程序"< cin.get(); return0; } 生产者和消费者主要通过P和V原语,来进行进程的同步于互斥,WaitForSingleObject(hSemEmptyBuffer,INFINITE);此条语句想当于一个P原语,初始值为3,即可以进行生产,生产成功之后,释放信号量hSemFullBuffer,这里的ReleaseSemaphore(hSemFullBuffer,1,&iFullBuffer);相当于一个V语句,每执行一次,信号量的值就增加1,只要hSemFullBuffer不为0,消费者就可以发出请求,开始消费。 下面来看消费者进程的控制代码 #include #pragmahdrstop #pragmaargsused #include"iostream.h" intmain(intargc,char*argv[]) { HANDLEhSemEmptyBuffer; HANDLEhSemFullBuffer; longintiEmptyBuffer=0; hSemEmptyBuffer=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EmptyBuff"); hSemFullBuffer=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FullBuff"); cout<<"试图取出物品"< cin.get(); WaitForSingleObject(hSemFullBuffer,INFINITE); /*************************************/ /**************互斥P******************/ /************具体操作*****************/ /**************互斥V******************/ /*************************************/ cout<<"成功取出物品,并准备通告"< cin.get(); ReleaseSemaphore(hSemEmptyBuffer,1,NULL); cout<<"新消费了一个产品,之前共有"< cout<<"通告完毕,正在消费物品。 。 。 。 "< cin.get(); cout<<"消费完毕,退出程序"< cin.get(); return0; } 实 验 结 果 及 分 析 分析: 初始状态下,信号量hSemFullBuffer的值为0,WaitForSingleObject(hSemFullBuffer,INFINITE);此条语句亦为一条P语句,有P原语的特点可知,此处程序不能顺序往下执行,必须等到其值大于等于1,方能从等待状态顺序执行,等生产者生产之后,施放了此信号量,消费者才能开始工作,消费者消费之后,会释放信号量hSemEmptyBuffer,ReleaseSemaphore(hSemEmptyBuffer,1,NULL);此条语句为V语句,执行此条指令后,信号量的值就加1,保证每消费一个产品,生产者至少可以继续生产一个 心 得 体 会 实验3.2 进程同步与互斥(苹果橘子问题) 实 验 内 容 实 验 要 求 ●学习并理解生产者/消费者模型及其同步/互斥规则; ●学习了解Windows同步对象及其特性; ●熟悉实验环境,掌握相关API的使用方法; ●设计程序,实现生产者/消费者进程(线程)的同步与互斥; ●提交实验报告。 小组成员 姓名 学号 组内分工 教师评分 小 组 成 绩 评 定 教师签名: 年月日 实 验 原 理 步 骤 ( 算 法 流 程 ) 苹果橘子问题参照的是生产者与消费者模型,父亲与母亲共同争夺一个盘子,而且一个盘子一次只能放一个水果,父亲与母亲构成互斥,同时父亲与儿子构成同步,父亲向儿子提供苹果,母亲给女儿提供橘子,但是儿子只能吃苹果,女儿只能吃橘子,这是程序设计的基本思想,下面是程序的设计流程图: 控制台主程序: #include #pragmahdrstop #pragmaargsused #include"iostream.h" /* HANDLECreateSemaphore( LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,//pointertosecurityattributes LONGlInitialCount,//initialcount LONGlMaximumCount,//maximumcount LPCTSTRlpName//pointertosemaphore-objectname ); */ intmain(intargc,char*argv[]) { //空盘子同步信号量 HANDLEhSem_Empty_Plate; hSem_Empty_Plate=CreateSemaphore(NULL,1,1,"Sem_Empty_Plate"); //苹果同步信号量 HANDLEhSem_Apple; hSem_Apple=CreateSemaphore(NULL,0,1,"Sem_Apple"); //桔子同步信号量 HANDLEhSem_Orange; hSem_Orange=CreateSemaphore(NULL,0,1,"Sem_Orange"); cout<<"SemaphoreOK."< cin.get(); CloseHandle(hSem_Empty_Plate); CloseHandle(hSem_Apple); CloseHandle(hSem_Orange); cout<<"SemaphoreOver."< //保持环境存在 cin.get(); return0; } 控制台代码段的作用是设置三个信号量,分别为hSem_Empty_Plate,hSem_Apple,hSem_Orange,并对其进行初始值设置,其初始值分别为1,0,0,即其初始状态为盘子为空,父亲和母亲可以争夺盘子的使用权。 父亲进程: #include #pragmahdrstop #pragmaargsused #include"iostream.h" intmain(intargc,char*argv[]) { HANDLEhSem_Empty_Plate; hSem_Empty_Plate=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Empty_Plate"); HANDLEhSem_Apple; hSem_Apple=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Apple"); inti; for(i=0;i<20;i++) { cout<<"试图放入苹果"< cin.get(); WaitForSingleObject(hSem_Empty_Plate,INFINITE); /*************************************/ /************具体操作*****************/ /*************************************/ cout<<"成功放入苹果,并准备通告儿子"< cin.get(); ReleaseSemaphore(hSem_Apple,1,NULL); cout<<"通告完毕,准备削苹果"< cin.get(); } cin.get(); return0; 父亲进程首先会执行WaitForSingleObject(hSem_Empty_Plate,INFINITE);这条语句想当与一条P原语,会首先判断盘子是否为空,即信号量hSem_Empty_plate是否为1,如果为1,则父亲进程可以顺序执行下面的程序,向盘子里放一个苹果,然后释放信号量hSem_Apple,使信号量加1,这里的ReleaseSemaphore(hSem_Apple,1,NULL);相当于一条V原语 儿子进程: #include #pragmahdrstop #pragmaargsused #include"iostream.h" intmain(intargc,char*argv[]) { HANDLEhSem_Empty_Plate; hSem_Empty_Plate=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Empty_Plate"); HANDLEhSem_Apple; hSem_Apple=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Apple"); inti; for(i=0;i<20;i++) { cout<<"试图取出苹果"< cin.get(); WaitForSingleObject(hSem_Apple,INFINITE); /*************************************/ /************具体操作*****************/ /*************************************/ cout<<"成功取出苹果,并准备通告老爹老妈"< cin.get(); ReleaseSemaphore(hSem_Empty_Plate,1,NULL); cout<<"通告完毕,正在吃苹果"< cin.get(); } cin.get(); return0; }。 儿子进程执行去苹果的任务,它一样会首先判断盘子是否有苹果,即判断苹果信号量hSem_Apple是否大于等于1,判断的c++语句为: WaitForSingleObject(hSem_Apple,INFINITE);其相当于一条P原语,没执行一次这条指令,信号量就减1,如果此处的信号量大于1,儿子进程就顺序执行,取苹果,吃苹果,然后再执行ReleaseSemaphore(hSem_Empty_Plate,1,NULL);释放信号量,使信号量hSem_Empty_Plate加1。 母亲进程: #include #pragmahdrstop #pragmaargsused #include"iostream.h" intmain(intargc,char*argv[]) { HANDLEhSem_Empty_Plate; hSem_Empty_Plate=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Empty_Plate"); HANDLEhSem_Orange; hSem_Orange=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"Sem_Orange"); inti; for(i=0;i<20;i++) { cout<<"试图放入桔子"< cin.get();
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统