当前位置:文档之家› 进程之间的同步互斥与通信理发师问题操作系统课程设计

进程之间的同步互斥与通信理发师问题操作系统课程设计

进程之间的同步互斥与通信理发师问题操作系统课程设计操作系统课程设计目录1. 课程设计目的 (3)2. 设计要求 (3)3. 问题具体描述 (3)4. 设计分析 (3)5. 设计分工 (4)6. 数据结构说明 (4)7. 系统结构说明 (4)8. 系统调用说明 (4)9. 分工设计说明 (5)10. 算法流程图 (5)11. 分工代码 (6)12. 整体代码 (7)13. 程序运行 (10)14. 总结 (11)1.课程设计目的1.内容围绕操作系统原理中最重要的基本概念和基本原理展开2.巩固对原理知识的学习效果3.加深对基本概念的理解4.学习如何将基本原理和实际设计、应用有机结合5.锻炼本专业的基本能力2.设计要求1:进程间通信、并发(同步/互斥)、文件读写2:内存管理、Dll、Windows消息机制、IO (尚未最终定型)3.问题具体描述1.完成N个生产者和M个消费者之间的并发控制,N、M不低于5,数据发送和接收缓冲区大小不小于10个。

2.某个生产者进程生产的消息供K个消费者进程消费。

K《=M。

某些消费进程消费多个生产者生产的消息。

生产者和消费者之间的对应关系可以在程序开始有一个文件中读入,也可以动态调整。

3.每个生产进程生产M个消息后结束运行。

如果一个消费者进程没有对应的生产者进程在运行后,也结束运行。

4.设计分析课程设计的主要目的是了解并且掌握进程之间的同步互斥,和进程之间的通信问题。

结合课本上的生产者与消费者问题可以从这方面来实现一个多进程的小系统,并且解决多个进程之间的通信,并发等问题,以此来达到课程设计的目的。

理发师问题是将顾客看做生产者,将理发师作为消费者。

设置一定数量的椅子的数目来作为缓存区的大小。

顾客来到的时候坐在椅子上,将自己作为“产品”,理发师理发的时候从椅子上叫走顾客,相当于消费“产品”,从而达到了课程设计要求的前一个要求。

顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。

并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得)。

主要有以下一些函数来实现整个问题的实现过程:(1)用随机函数random()来产生进入理发店的顾客。

(2)定义理发师的理发函数cuthair()用来实现理发操作。

(3)定义顾客被理发的函数gethaircut()用来实现顾客被理发的操作。

(4)用顾客线程customer实现对顾客行为的控制。

(5)用理发师线程barber实现对理发师行为的控制。

(6)定义主函数main实现对两个线程的控制和执行操作。

5.设计分工成员:李宁侯绍立分工:理发师进程、信号量的设置、理发师函数:xxx顾客进程、顾客函数、主函数:xx6.数据结构说明本程序用到了数据结构中的队列,理发的顾客由随机函数产生,顾客遵从先到先理发的原则,但队列的长度限制为输入的理发店中的椅子的个数,当理发店的椅子没有空位的时候,到来的顾客主动退出加入队列。

理发师对队列中的顾客进行先到先服务的原则理发。

7. 系统结构说明(一)头文件声明#include "windows.h"#include "iostream.h"#include "math.h"(二)定义各种变量int long waiting(0);int chairs;char open_door;char close_door;int count(0);int finish(0);(三)信号量的定义HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex");HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers");HANDLE customers =::CreateSemaphore(NULL,0,3,"customers");8. 系统调用说明(1)CreateThread():创建线程(2)CreateMutex():找出当前系统是否已经存在指定进程的实例。

如果没有则创建一个互斥体,用来同步。

如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

CreateMutex()函数可用来创建一个有名或无名的互斥量对象(3)CreateSemaphore():CreateSemaphore() 是系统提供的API,包含在Windows.h 中,应用在同步的处理中。

作用是创建一个新的信号机,执行成功,返回信号机对象的句柄;零表示出错。

一旦不再需要,一定记住用CloseHandle关闭信号机的句柄。

它的所有句柄都关闭以后,对象自己也会删除。

一旦值大于零,信号机就会触发(发出信号)。

Semaphore是一个同步问题机制,不论是Event或Mutex,其他Process在执WaitForSingleObject时,就看当时的物件是Signal或UnSignal而决定是否等待,而Semaphore也相同,但是它要变成Signal/UnSignal的状态,却有些不同,它是提供一个计数值,它允许在这个计数值之内,任何执行到WaitForSingleObject的Thread都不会停下来,而且每执行WaitForSingleObject一次,计数值就减一,当计数值变成0时,该Semaphore才会处於UnSignal的状态,而某个Thread ReleaseSemaphore时,便会将计数值增加,以便其他的Thread或本身可得Signal的讯号,而使WaitForSingleObject停止等待。

(4)ReleaseSemaphore():ReleaseSemaphore ()函数的作用是增加信号机的计数。

如果成功,就调用信号机上的一个等待函数来减少它的计数。

(5)WaitForSingleObject():函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。

参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。

若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

(6)ResumeThread():线程恢复函数,使用该函数能激活线程的运行,使CPU分配资源让线程恢复运行。

(7)ReleaseMutex():释放由线程拥有的一个互斥体(8)Sleep():睡眠等待9. 分工设计说明需要用到的信号量:HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex");实现顾客与理发师对公用缓存区的互斥操作HANDLE barbers=::CreateSemaphore(NULL, 1,1, "barbers"); HANDLE customers=::CreateSemaphore(NULL,0,3,"customers"); ::WaitForSingleObject(customers,INFINITE); 等待顾客进程的V(customer)操作::WaitForSingleObject(Mutex,INFINITE); 申请操作顾客与理发师公用的缓存区::ReleaseSemaphore(barbers,1,NULL); 释放信号量barbers::ReleaseMutex(Mutex); 释放信号量Mutex,允许顾客操作缓存区10.算法流程图11.分工代码#include "windows.h"#include "iostream.h"#include "math.h"int long waiting(0); //等待理发的顾客人数int chairs; //店中椅子的总数目char open_door; //开门char close_door; //关门int count(0); //顾客的序号int finish(0); //已经理完发的顾客人数DWORD a;HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex"); //用来实现进程的互斥HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers"); //定义信号量来进行线程间的同步HANDLE customers =::CreateSemaphore(NULL,0,3,"customers"); //定义信号量来进行线程间的同步int random()//定义随机函数来产生顾客,并使两个顾客间的时间少于15秒{return (rand()*15000)/RAND_MAX;}void cuthair()//理发师的理发函数,用时15秒{::Sleep (15000);cout<<"理发结束!"<<endl;}DWORD WINAPI barber(LPVOID pParm1) //理发师线程{while(true){::WaitForSingleObject(customers,INFINITE) ;//p(customers),等待顾客::WaitForSingleObject(Mutex,INFINITE); //等待互斥量waiting--;//等待的人数减1::ReleaseSemaphore(barbers,1,NULL);//释放信号量::ResumeThread(barbers);//唤醒顾客进程::ReleaseMutex(Mutex);//v(mutex);cuthair();finish++;}return 0;}12.整体代码#include "windows.h"#include "iostream.h"#include "math.h"int long waiting(0); //等待理发的顾客人数int chairs; //店中椅子的总数目char open_door; //开门char close_door; //关门int count(0); //顾客的序号int finish(0); //已经理完发的顾客人数DWORD a;HANDLE Mutex =::CreateMutex(NULL, FALSE, "Mutex"); //用来实现进程的互斥HANDLE barbers =::CreateSemaphore(NULL, 1,1, "barbers"); //定义信号量来进行线程间的同步HANDLE customers =::CreateSemaphore(NULL,0,3,"customers"); //定义信号量来进行线程间的同步int random()//定义随机函数来产生顾客,并使两个顾客间的时间少于15秒{return (rand()*15000)/RAND_MAX;}void cuthair()//理发师的理发函数,用时15秒{::Sleep (15000);cout<<"理发结束!"<<endl;}void gethaircut()// 顾客被理发的函数{::Sleep (15001); //顾客被理发的函数,为了和理发师之间有所区别,比理发师理发时间长1毫秒cout<<"第"<<finish<<"个顾客理发完毕,离开"<<endl;}DWORD WINAPI customer(LPVOID pParm2) // 顾客线程{::WaitForSingleObject(Mutex ,INFINITE); //P(mutex)来进行互斥操作count++;//来的是第几个顾客cout<<"顾客敲门!第"<<count<<" 个顾客到来"<<endl;if (waiting<chairs)//如果有空椅子{if (waiting!=0){cout<<"现在有"<<waiting <<" 个人在等待理发"<<endl;}elsecout<<"无人在等待理发"<<endl; //输出有多少人在等待waiting++;cout<<"剩余"<<chairs-waiting+1<<"个座位"<<endl;cout<<"有空位,顾客已坐下"<<endl;::ReleaseSemaphore(customers,1,NULL); //V(customer)::ResumeThread(customers); //唤醒理发师进程::ReleaseMutex(Mutex); //释放互斥量,以便其他线程使用::WaitForSingleObject(barbers,INFINITE);//等待理发gethaircut();}else{cout<<"没有空椅子,第"<<count<<"个顾客离开理发店"<<endl; //没有椅子,顾客直接离开::ReleaseMutex(Mutex);}return 0;}DWORD WINAPI barber(LPVOID pParm1) //理发师线程{while(true){::WaitForSingleObject(customers,INFINITE) ;//p(customers),等待顾客::WaitForSingleObject(Mutex,INFINITE); //等待互斥量waiting--;//等待的人数减1::ReleaseSemaphore(barbers,1,NULL);//释放信号量::ResumeThread(barbers);//唤醒顾客进程::ReleaseMutex(Mutex);//v(mutex);cuthair();finish++;}return 0;}int main(int argc, char* argv[])//实现线程的操作{cout<<"输入理发店中的椅子个数:"; cin>>chairs;cout<<"店中有"<<chairs<<"把椅子"<<endl; //设置椅子数目cout<<"是否开始接待顾客?Y/N"<<endl;//是否开门营业cin>>open_door;while (open_door!='y'){cout<<endl<<"尚未营业!"<<endl;cout<<"是否开始接待顾客?Y/N"<<endl;cin>>open_door;}HANDLE hThread1;HANDLE hThread2;hThread2=::CreateThread(NULL,0,barber,NULL,0,NULL); //产生一个理发师进程while(close_door!='y'){::Sleep(random());//函数实现顾客随机到来hThread1=::CreateThread(NULL,0,customer, NULL,a,NULL);cout<<endl<<"正在营业,请进!"<<endl;if (finish>=8 && waiting==0)//如果完成数超过8并且没有人等待{cout<<"已经为"<<finish<<"个顾客理发了,是否停止营业?"<<endl; //提示是否关门cin>>close_door;return close_door;}}if (close_door=='y'){cout<<"暂停营业!欢迎下次光临!"<<endl;return 0;}return 0;}13.程序运行开始输入椅子数目选择是否接待顾客接待顾客理发完毕14.总结通过这个课程设计,对于课本上的关于进程之间的同步、互斥有了更深层的认识,而且有了具体上直观上的理解。

相关主题