操作系统大作业&相关知识整理
我校的操作系统大作业为N选3,以下为三个较为简单的例子的实现
参考代码 见连接
1. 银行柜员服务问题
进程间同步/互斥问题
通过该实验熟悉信号量的处理及其在多线程程序中的应用
实验题目
题目描述:
银行有n个柜员负责为顾客服务,顾客进入银行先取一个号码,>然后等着叫号。当某个柜员空闲下来,就叫下一个号。
编程实现该问题,用P、V操作实现柜员和顾客的同步。
实现要求:
1. 某个号码只能由一名顾客取得;
2. 不能有多于一个柜员叫同一个号;
3. 有顾客的时候,柜员才叫号;
4. 无柜员空闲的时候,顾客需要等待;
5. 无顾客的时候,柜员需要等待。
实验环境:
Windows10
VS2015
设计思路&程序结构
题目要求顾客取号与柜台叫号通过互斥对象完成,故建立两个信号量分别作为取号与叫号的信号量。
此外,题目要求顾客与柜台间进行同步操作,为每个顾客分配一个信号量用于完成顾客与柜台间的同步。具体实现可参考项目代码,其中进行了详细的注释
题目整体完成过程如下:
首先从输入文件读取各个顾客的信息
而后创建时钟函数用于记录程序开始的时间(程序中时钟周期记录在T中)
接下来依次创建柜台实例并为每个柜台开启一个线程,该线程进行忙等待直至有顾客等待(waitlist队列长度不为0),则叫号并开始服务。
为每个柜台开启叫号线程后顾客开始进入,判定顾客进入的方法同样为忙等待,判定当前时间每个顾客是否应当进入,若到达其进入时间则为其开启一个取号线程。
当所有顾客服务结束后输出最终结果。
题目整体完成结构见main.cpp中的int main() 及 void start()
模拟时钟计时操作如下:
定义了一个全局变量time用于记录当前时刻,clock线程不断循环睡眠Tms,每两次睡眠之间time自增一次,即完成了用time记录当前时刻的功能
模拟时钟过程见main.cpp中的void clock()
模拟顾客取号操作过程如下:
定义了全局变量M_GET_NUM为用户取号信号量,全局变量NUM为当前号码。此外定义了顾客等待队列waitlist用于记录当前在排队的顾客及其顺序。M_CUSTOM为顾客柜台同步信号量,用于保护服务过程中可能用到的资源,在用户实例初始化时进行P操作。当用户取号时,先对该信号量进行一次P操作,而后记录当前号码NUM为该顾客取得的号码,当前号码加一。将该顾客加入到排队的队列waitlist中。顾客取号操作完毕,对M_GET_NUM进行V操作
顾客取号过程见main.cpp中的void Get_num(customer *this_customer)
模拟柜台叫号操作过程如下:
定义了全局变量M_CALL_NUM为柜台叫号信号量,全局变量NUM_DONE为当前已完成服务的顾客数。当柜台叫号时,先对M_CALL_NUM进行P操作,而后判断当前等待队列waitlist是否为空,若不为空则直接对M_CALL_NUM进行V操作,继续进行忙等待,否则对当前等待队列waitlist中的队首取出,从队列中移除,叫号过程结束,对M_CALL_NUM进行V操作,而后对刚刚取出的其进行服务。开始服务时被服务的顾客记录当前时刻为开始服务时刻,当前柜台为服务柜台。服务过程通过Sleep函数模拟,服务结束后顾客记录当前时间为结束服务时间,并对M_CUSTOM进行V操作,即服务完成顾客用于服务的相应资源可继续用于其他用途。柜台在服务完成后继续开始叫号。
柜台叫号过程见main.cpp中的void Call_num(server *this_server)