操作系统课程设计.docx
《操作系统课程设计.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计.docx(11页珍藏版)》请在冰豆网上搜索。
![操作系统课程设计.docx](https://file1.bdocx.com/fileroot1/2022-12/29/00214ec1-60e3-4f5f-9250-90cd33cb3bcd/00214ec1-60e3-4f5f-9250-90cd33cb3bcd1.gif)
操作系统课程设计
计算机与信息学院
操作系统课程设计
专业班级
信息安全10-02班
学生姓名及学号
刘禹20103046
课程教学班号
0002
任课教师
田卫东老师
实验指导教师
田卫东老师
实验地点
逸夫实验楼507
2012~2013学年第2学期
1、题目:
多进程/线程编程:
哲学家问题。
设置进程/线程,描述哲学家;
随机启动哲学家,显示进程/线程执行状态;
随着线程的执行,更新显示;
编写正确的哲学家程序,设法延迟线程的执行,使之出现死锁;
编写正确的哲学家程序,保证不出现死锁;
题目描述:
哲学家问题:
由Dijkstra提出并解决,是典型的同步问题。
问题描述有多个(设为number)哲学家共用一张圆桌,分别坐在周围number个椅子上,在圆桌上有number个碗和number个筷子,他们的生活方式是交替地进行思考和进餐。
平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐,进餐完毕,放下筷子继续思考。
2、开发环境:
开发工具:
VisualC++6.0;
开发环境:
Windows下多进程/线程编程
开发语言:
C++
3、总体算法:
设哲学家人数为number(程序中赋值为5),采用哲学家问题的一种解法:
(1)采用p、v操作,哲学家拿起筷子后就持有该资源,等到吃完放下筷子后其他哲学家才能拿起该筷子;同样,哲学家需要的某筷子被其他哲学家持有时,等待,进程因而阻塞。
(2)第一个到第number-1个哲学家采用一种进程描述,先左手拿筷子,之后右手才能拿。
(3)只有最后一个哲学家定义另一进程:
必须拿右手边筷子,之后再拿左手边的筷子。
(4)所采用方法其实质是编号资源的方法,把筷子看为临界资源,按其序号编号,哲学家只能由小到大申请资源即为本算法。
(5)出现死锁的方法:
最后一个哲学家也是先拿左手边的筷子,再拿右手边的筷子时就容易出现死锁。
4、详细设计
1.若干常量、变量的定义:
constintnumber=5;//哲学家人数
constintsleep_time=10;//显示时间
constinteating_time=50;//吃饭显示的时间
CRITICAL_SECTIONchopstics[number];//临界资源:
筷子
CRITICAL_SECTIONcs;//控制打印的临界区变量,由于一段时间只能允许一个进程打印到屏幕,所以屏幕也为临界资源
2.状态显示函数:
定义了若干函数显示当前状态:
thingking(inti)(哲学家i正在思考),
hungry(inti)(饥饿),
pickup(inti,intj)(哲学家i拿起了筷子j),
eating(inti)(正在吃饭),
putdown(inti,intj)(哲学家i放下筷子j)。
另外定义了函数xianshi(inti),每个状态显示函数都调用该函数,显示当前调用的进程。
3.线程定义体:
(1)参数为void*i,i即为调用的进程号,由于void*表示为任意类型的指针,所以要强制类型转换:
intnum=(int)i;
(2)pv操作的实现方法:
EnterCriticalSection(),LeaveCriticalSection(),
EnterCriticalSection(&chopstics[num]);//拿起左手边的筷子
pickup(num,num);
EnterCriticalSection(&chopstics[(num+1)%5]);//拿起右手边的筷子
pickup(num,num+1);
eating(num);//吃饭
LeaveCriticalSection(&chopstics[num]);//放下左边的筷子
putdown(num,num);
LeaveCriticalSection(&chopstics[(num+1)%5]);//放下右边的筷子
putdown(num,num+1);
(3)线程主体为死循环,没有资源时阻塞
4.主进程main():
(1)main函数代码如下:
HANDLEhThread[number];
InitializeCriticalSection(&cs);
//循环建立线程0-3
for(inti=0;i{
InitializeCriticalSection(&chopstics[i]);
hThread[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,(void*)i,0,NULL);
}
//建立线程4
InitializeCriticalSection(&chopstics[number-1]);
//让其不出现死锁的定义,最后一个哲学家先拿右边筷子,再拿左边筷子
//hThread[number-1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,(void*)(number-1),0,NULL);
//出现死锁的定义,最后一个哲学家和其他哲学家一样,也是先拿左边筷子,再拿右边筷子
hThread[number-1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,(void*)(number-1),0,NULL);
//等待所有hThread有效
//等待所有线程执行完
WaitForMultipleObjects(number,hThread,true,INFINITE);
for(i=0;i{
LeaveCriticalSection(&chopstics[i]);
CloseHandle(hThread[i]);
}
LeaveCriticalSection(&cs);
相关说明:
1)初始所有临界区都要初始化,用InitializeCriticalSection()函数。
2)线程的定义用_beginthreadex()函数。
_beginthreadex()函数的原型为unsignedlong_beginthreadex(void*security,unsignedstack_size,unsigne(__stdcall*start_address)(void*),void*arglist,/*传给线程函数的参数的指针*/unsignedinitflag,unsigned*thrdaddr);,用到该函数必须链接多线程库文件,步骤为:
projectsetting->c/c++->CodeGenerator->userun-timelibrary->MulitthreadedDLL
3)主进程最后用WaitForMultipleObjects(number,hThread,true,INFINITE);等待所有线程都执行完,否则阻塞。
由于线程定义都是死循环,不可能执行完,所以这之后的语句执行不到。
此句的作用:
一,当不出现死锁时可以一直执行线程,
二,是当出现死锁时,由于各线程阻塞也没法执行完,主进程因此也阻塞,最后出现死锁。
五、执行结果
一、不出现死锁:
二、出现死锁!
!
!
六、总结
以前没有接触过多线程编程的内容,这一次为做本课程设计完全自学了好多内容。
从网上搜了好多资料,一有不会的就XX。
做的过程中也走了些弯路。
比如开始时搞忘了数组是从0开始的,实际应是从0-(number-1),好多函数的参数搞错了;还有当初不知道怎样实现pv操作;还有开始并没有完全弄清,不清楚main函数是主进程,也是会调用的,因此开始写的程序结果也不对,然后问别人才弄清楚的;程序写完后想润色一下,想把WaitForMultipleObjects()做为if语句的条件判断,若出现死锁则显示:
出现死
锁!
,运行却并不行,想了会才知道已经出现了死锁程序就阻塞了怎么可能还会继续运行,还是因为当初没弄清。
做完后很有成就感和充实感,因为学会了很多东西,从以前对多线程一无所知,到开始入门有所了解,而且还加深了对操作系统课本相关知识的理解。
总之,做完后“感觉很好”!
现在已经注意到实践的重要,以后会多动手编程,锻炼编程能力的同时还会加深对知识的理解,同时还能培养兴趣。
七、代码
#include
#include
#include
constintnumber=5;//哲学家人数
constintsleep_time=10;//显示时间
constinteating_time=50;//吃饭显示的时间
CRITICAL_SECTIONchopstics[number];//临界资源:
筷子
CRITICAL_SECTIONcs;//控制打印的临界区变量
//////////////////////////////////////////////////////////////////////////
//状态显示函数
//显示被调用线程
voidxianshi(inti){
EnterCriticalSection(&cs);
cout<<"线程"<
"<<"";
LeaveCriticalSection(&cs);
return;
}
//正在思考
voidthinking(inti){
EnterCriticalSection(&cs);
xianshi(i);
cout<<"哲学家"<
Sleep(sleep_time);
LeaveCriticalSection(&cs);
return;
}
//正饥饿
voidhungry(inti){
EnterCriticalSection(&cs);
xianshi(i);
cout<<"哲学家"<
Sleep(sleep_time);
LeaveCriticalSection(&cs);
return;
}
//哲学家i拿起了筷子j
voidpickup(inti,intj){
EnterCriticalSection(&cs);
xianshi(i);
if(j==i)
{
cout<<"哲学家"<
-"<}elseif(i==number-1)
{
cout<<"哲学家"<
-"<<0<}else
cout<<"哲学家"<
-"<Sleep(sleep_time);
LeaveCriticalSection(&cs);
return;
}
//显示正在吃饭
voideating(inti){
EnterCriticalSection(&cs);
xianshi(i);
cout<<"哲学家"<
Sleep(eating_time);
LeaveCriticalSection(&cs);
return;
}
//显示放下筷子
voidputdown(inti,intj){
EnterCriticalSection(&cs);
xianshi(i);
if(j==i)
{
cout<<"哲学家"<
+"<}elseif(i==number-1)
{
cout<<"哲学家"<
+"<<0<}else
{
cout<<"哲学家"<
+"<}
Sleep(sleep_time);
LeaveCriticalSection(&cs);
return;
}
/////////////////////////////////////////////////////////////////////////
//线程定义
//用于定义哲学家1-4
UINTWINAPIThreadFunc1(void*i){
intnum=(int)i;
while
(1)
{
thinking(num);
hungry(num);
//wait=WaitForSingleObject(mutex[num],INFINITE);
EnterCriticalSection(&chopstics[num]);//拿起左手边的筷子
pickup(num,num);
//wait=WaitForSingleObject(mutex[num+1],INFINITE);
EnterCriticalSection(&chopstics[(num+1)%5]);//拿起右手边的筷子
pickup(num,num+1);
eating(num);
LeaveCriticalSection(&chopstics[num]);//放下左边的筷子
//ReleaseMutex(mutex[num]);
putdown(num,num);
//ReleaseMutex(mutex[num+1]);
LeaveCriticalSection(&chopstics[(num+1)%5]);//放下右边的筷子
putdown(num,num+1);
}
return1;
}
//用于定义哲学家5
UINTWINAPIThreadFunc2(void*i){
intnum=(int)i;
while
(1)
{
thinking(num);
hungry(num);
//wait=WaitForSingleObject(mutex[0],INFINITE);
EnterCriticalSection(&chopstics[0]);//拿起右手边的筷子
pickup(num,0);
//wait=WaitForSingleObject(mutex[num],INFINITE);
EnterCriticalSection(&chopstics[num-1]);//拿起左手边的筷子
pickup(num,num);
eating(num);
//ReleaseMutex(mutex[0]);
LeaveCriticalSection(&chopstics[0]);//放下左边的筷子
putdown(num,0);
//ReleaseMutex(mutex[num]);
LeaveCriticalSection(&chopstics[num-1]);//放下右边的筷子
putdown(num,num);
}
return1;
}
//////////////////////////////////////////////////////////////////////////
intmain()
{
HANDLEhThread[number];
//HANDLEhThread2[number];
InitializeCriticalSection(&cs);
//循环建立线程0-3
for(inti=0;i{
//mutex[i]=CreateMutex(NULL,FALSE,"");
InitializeCriticalSection(&chopstics[i]);
hThread[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,(void*)i,0,NULL);
}
//建立线程4
InitializeCriticalSection(&chopstics[number-1]);
//让其不出现死锁的定义,最后一个哲学家先拿右边筷子,再拿左边筷子
//hThread[number-1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,(void*)(number-1),0,NULL);
//出现死锁的定义,最后一个哲学家和其他哲学家一样,也是先拿左边筷子,再拿右边筷子
hThread[number-1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,(void*)(number-1),0,NULL);
//等待所有hThread有效
/*if(WaitForMultipleObjects(5,hThread2,true,INFINITE))
{
cout<<"出现死锁!
!
"<}*/
//等待所有线程执行完
WaitForMultipleObjects(number,hThread,true,INFINITE);
for(i=0;i{
LeaveCriticalSection(&chopstics[i]);
CloseHandle(hThread[i]);
}
LeaveCriticalSection(&cs);
return0;
}