操作系统课程设计报告
学院:计算机科学与信息学院
专业: 计算机科学与技术
班级:计科 083
姓 名
实验时间
学 号
2010,12
指导教师
实验项目名称
P,V 操作
实验组
成 绩
掌握信号量方式实现进程同步的一般方法,了解系统实现“阻塞”和“唤醒”功能的方
法和技巧。同时掌握进程同步和互斥的概念及实现技术。
编程模拟实现下列任一问题:
1.桌上有一盘子,可以存放一个水果。爸爸总是放苹果到盘子中,而妈妈总是放香蕉到盘子中;
一个儿子专等吃盘中的香蕉,一个女儿专等吃盘中的苹果。请用 P,V 操作实现上述问题的解。
实
验
目
的
实
验
内
容
及
要
求
实
验
环
境
硬件环境:
软件环境:系统 :windows 7 开发平台:vc6.0
在本题中,爸爸、妈妈、儿子和女儿共用一个盘子,盘子一次只能放一个水果。当盘子为空
时,爸爸和妈妈都可以试着将一个水果放入盘中,但一次只能有一人成功放入水果。若放入盘
子中的是香蕉,则允许儿子吃,女儿必须等待;若放入盘子中的是苹果,则允许女儿吃,儿子
必须等待。
在本题中,应设置 3 个信号量 dish、apple、banaba,信号量 dish 表示盘子是否为空,
其初值为 1;信号量 apple 表示盘中是否有苹果,其初值为 0;信号量 banana 表示盘中是否
有香蕉,其初值为 0。设计界面如图:
总
体
设
计
分别用 4 个 button 控件来模拟爸爸放苹果、妈妈放香蕉、儿子吃香蕉和女儿吃苹果 4 个进
程,用以个文本框输出当前盘子的状态.
程
序
框
图
及
流
程
图
father 进程流程图
mather 进程流程图
son 进程流程图
daughter 进程流程图
主
要
源
代
码
及
注
释
#include//声明使用队列
using namespace std;
struct semaphore{//定义记录数据结构
int value;//信号量的值
queue L;//阻塞队列
};
semaphore dish;//定义盘子信号量
semaphore apple;//定义苹果信号量
semaphore banana;//定义香蕉信号量
int bz;//标记进程
void p(semaphore &s);//p 操作
void v(semaphore &s);//v 操作
void wakeup(semaphore &s);//唤醒操作
void CMyDlg::p(semaphore &s)//p 操作实现
{
s.value=s.value-1;
if(s.value<0) s.L.push(bz);//模拟进程阻塞
}
void CMyDlg::v(semaphore &s)//v 操作实现
{
s.value=s.value+1;
if(s.value<=0) {wakeup(s);}//唤醒
}
void CMyDlg::wakeup(semaphore &s)//唤醒实现
{
int f=s.L.front();//阻塞队列对头出对
s.L.pop();//阻塞进程出对
//模拟唤醒 son 进程
if(f==1){
MessageBox("son 进程执行成功","唤醒阻塞进程");//输出
m_bson.EnableWindow(true);//让控件生效
m_dish="empty";//更新盘子状态
UpdateData(FALSE);//更新控件关联变量
v(dish);//dish 执行 v 操作
}
//唤醒 daughter 进程
else if(f==2){
MessageBox("daughter 进程执行成功","唤醒阻塞进程");//输出
m_dish="empty";//盘子当前的状态
m_bdaughter.EnableWindow(true);//让控件生效
UpdateData(FALSE);//更新控件关联变量
v(dish);//dish 执行 v 操作
}
//唤醒 father 进程
else if(f==3){
MessageBox("father 进程执行成功","唤醒阻塞进程");//输出
m_dish="apple";//盘子当前的状态
m_bfather.EnableWindow(true);//让控件生效
UpdateData(FALSE); //更新控件关联变量
v(apple);//apple 执行 v 操作
}
//唤醒 mather 进程
else if(f==4) {
MessageBox("mather 进程执行成功","唤醒阻塞进程");//输出提示
m_dish="banana";//盘子当前的状态
m_bmather.EnableWindow(true);//让控件生效
UpdateData(FALSE);//更新控件关联变量
v(banana);//banana 执行 v 操作
}
}
void CMyDlg::OnBUTTONfather() //爸爸进程
{
// TODO: Add your control notification handler code here
bz=3;//进程标识
p(dish);//执行 p 操作
if(dish.value<0) { //判断是否被阻塞
MessageBox("father 进程被阻塞","阻塞进程");//输出提示
m_bfather.EnableWindow (false);//让控件失效模拟进程阻塞
}
else {
bz=0;
MessageBox("father 放苹果成功","执行成功");//输出提示
m_dish="apple";//改变盘子状态
UpdateData(FALSE);//更新控件变量
v(apple);//执行 v 操作
}
}
void CMyDlg::OnBUTTONmather() //妈妈进程
{
// TODO: Add your control notification handler code here
bz=4;//进程标识
p(dish);//执行 p 操作
if(dish.value<0) { //判断是否被阻塞
MessageBox("mather 进程被阻塞","阻塞进程");//输出提示
m_bmather.EnableWindow(false);//让控件失效模拟进程阻塞
}
else {
bz=0;
MessageBox("mather 放香蕉成功","执行成功");//输出提示
m_dish="banana";//改变盘子状态
UpdateData(FALSE);//更新控件变量
v(banana);//执行 v 操作
}
}
void CMyDlg::OnBUTTONson() //儿子进程
{
// TODO: Add your control notification handler code here
bz=1;//进程标识
p(banana);//执行 p 操作
if(banana.value<0) { //判断是否被阻塞
MessageBox("son 进程被阻塞","阻塞进程");//输出提示
m_bson.EnableWindow(false);//让控件失效模拟进程阻塞
}
else {
bz=0;
MessageBox("son 吃香蕉成功","执行成功");//输出提示
m_dish="empty";//改变盘子状态
UpdateData(FALSE);//更新控件变量
v(dish);//执行 v 操作
}
}
void CMyDlg::OnBUTTONdaughter() //女儿进程
{
// TODO: Add your control notification handler code here
bz=2;//进程标识
p(apple);//执行 p 操作
if(apple.value<0) { //判断是否被阻塞
MessageBox("daugher 进程被阻塞","阻塞进程");//输出提示
m_bdaughter.EnableWindow(false);//让控件失效模拟进程阻塞
}
else {
bz=0;
MessageBox("daughter 吃苹果成功","执行成功");//输出提示
m_dish="empty";//改变盘子状态
UpdateData(FALSE);//更新控件变量
v(dish);//执行 v 操作
}
}