南昌大学操作系统实验报告.docx

上传人:b****0 文档编号:16862700 上传时间:2023-07-19 格式:DOCX 页数:42 大小:371.41KB
下载 相关 举报
南昌大学操作系统实验报告.docx_第1页
第1页 / 共42页
南昌大学操作系统实验报告.docx_第2页
第2页 / 共42页
南昌大学操作系统实验报告.docx_第3页
第3页 / 共42页
南昌大学操作系统实验报告.docx_第4页
第4页 / 共42页
南昌大学操作系统实验报告.docx_第5页
第5页 / 共42页
南昌大学操作系统实验报告.docx_第6页
第6页 / 共42页
南昌大学操作系统实验报告.docx_第7页
第7页 / 共42页
南昌大学操作系统实验报告.docx_第8页
第8页 / 共42页
南昌大学操作系统实验报告.docx_第9页
第9页 / 共42页
南昌大学操作系统实验报告.docx_第10页
第10页 / 共42页
南昌大学操作系统实验报告.docx_第11页
第11页 / 共42页
南昌大学操作系统实验报告.docx_第12页
第12页 / 共42页
南昌大学操作系统实验报告.docx_第13页
第13页 / 共42页
南昌大学操作系统实验报告.docx_第14页
第14页 / 共42页
南昌大学操作系统实验报告.docx_第15页
第15页 / 共42页
南昌大学操作系统实验报告.docx_第16页
第16页 / 共42页
南昌大学操作系统实验报告.docx_第17页
第17页 / 共42页
南昌大学操作系统实验报告.docx_第18页
第18页 / 共42页
南昌大学操作系统实验报告.docx_第19页
第19页 / 共42页
南昌大学操作系统实验报告.docx_第20页
第20页 / 共42页
亲,该文档总共42页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

南昌大学操作系统实验报告.docx

《南昌大学操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《南昌大学操作系统实验报告.docx(42页珍藏版)》请在冰点文库上搜索。

南昌大学操作系统实验报告.docx

南昌大学操作系统实验报告

实验报告

实验课程:

计算机操作系统

学生姓名:

郭慧

学号:

6100512019

专业班级:

电子商务121班

2014年5月30日

 

目录

一、实验一………………………………………………………03

二、实验二………………………………………………………12

三、实验三………………………………………………………19

 

南昌大学实验报告

学生姓名:

郭慧学号:

6100512019专业班级:

电子商务121班

实验类型:

□验证□综合□设计□创新实验日期:

2014-5-16实验成绩:

实验1进程/线程同步

一、实验目的

本实验讨论临界区问题及其解决方案。

首先创建两个共享数据资源的并发线程。

在没有同步控制机制的情况下,我们将看到某些异常现象。

针对观察到的现象,本实验采用两套解决方案:

•利用Windows的mutex机制

•采用软件方案

然后比较这两种方案的性能优劣。

二、实验内容

2.1进程/线程并发执行

Windows操作系统支持抢先式调度,这意味着一线程运行一段时间后,操作系统会暂停其运行并启动另一线程。

也就是说,进程内的所有线程会以不可预知的步调并发执行。

为了制造混乱,我们首先创建两个线程t1和t2。

父线程(主线程)定义两个全局变量,比如accnt1和accnt2。

每个变量表示一个银行账户,其值表示该账户的存款余额,初始值为0。

线程模拟在两个账户之间进行转账的交易。

也即,每个线程首先读取两个账户的余额,然后产生一个随机数r,在其中一个账户上减去该数,在另一个账户上加上该数。

线程操作的代码框架如下:

counter=0;

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2−r;

counter++;

}while(accnt1+accnt2==0);

print(counter);

两个线程执行相同的代码。

只要它们的执行过程不相互交叉,那么两个账户的余额之和将永远是0。

但如果发生了交叉,那么某线程就有可能读到新的accnt1值和老的accnt2值,从而导致账户余额数据发生混乱。

线程一旦检测到混乱的发生,便终止循环并打印交易的次数(counter)。

请编写出完整的程序代码并运行,然后观察产生混乱需要的时间长短。

因为这是我们编写的第一个程序,因此这里我给出了完整的代码,请参考。

有能力的同学在参考下面的代码之前,请先自己尝试一下。

#include

#include

#include

intaccnt1=0;

intaccnt2=0;

DWORDWINAPIrun(LPVOIDp){

intcounter=0;

inttmp1,tmp2,r;

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2−r;

counter++;

}while(accnt1+accnt2==0);

printf(”%d\n”,counter);

}

intmain(intargc,char∗argv[])

{

CreateThread(NULL,

0,

run,

NULL,

0,

NULL);

CreateThread(NULL,

0,

run,

NULL,

0,

NULL);

system(“PAUSE”);

return0;

}

反复运行该程序。

请问,观察到了什么?

你能解释这些现象吗?

2.2临界区问题之解决方案

上面例子中,线程执行的代码叫做临界区,因为两个线程在这里访问了同样的数据,

在没有保护的情况下,有可能发生混乱。

解决该问题有两套方案。

其一,如果操作系统提

供了同步原语,例如mutex,那么就可直接利用该原语对临界区进行排它性的存取保护。

二,如果操作系统不提供这样的原语,那么可用软件方案加以解决。

本实验中,我们将实

现并比较这两种方案。

2.2.1mutex方案

Windows操作系统提供了mutex对象。

mutex状态可以是signaled(unlocked)或者是nonsignaled(locked)。

利用mutex对象,可以方便地实现临界区保护。

进入临界区时(在第一个读操作之前),锁住mutex对象;离开临界区时(在第二个写操作之后),打开mutex对象。

线程的阻塞与唤醒由系统管理,程序员无需干预。

以下给出的是在Windows操作系统下有关mutex对象操作的提示。

创建一个未上锁mutex对象的代码如下:

HANDLEhMutex=CreateMutex(NULL,

FALSE,

NULL);

给mutex对象上锁的代码如下:

WaitForSingleObject(hMutex,INFINITE);

打开mutex对象的代码如下:

ReleaseMutex(hMutex);

根据以上提示,编写出用mutex对象保护临界区的解决方案。

完成后,请思考以下问题:

假设把加锁和开锁操作分别放置在第一个写操作之前和第二个写操作之后,能否实现临界区的保护,为什么?

2.2.2软件方案

现在假设操作系统没有提供同步原语。

这时,我们只能通过编程语言对变量的操作实现临界区保护。

下面给出的是一个概念性的解决方案框架:

intc1=0,c2=0,willwait;

cobegin

p1:

while

(1){

c1=1;

willwait=1;

while(c2&&(willwait==1));/∗waitloop∗/

CS1;

c1=0;

program1;

}

p2:

while

(1){

c2=1;

willwait=2;

while(c1&&(willwait==2));/∗waitloop∗/

CS2;

c2=0;

program2;

}

上面的方案使用了三个变量c1,c2和willwait。

线程i试图进入临界区时首先把变量ci置为1,接着把变量willwait的值设置为i(为什么?

)阻塞通过临界区之前的循环实现。

当线程退出临界区时,又把变量ci的值设置为0。

在我们的例子中,临界区始于第一个读操作,结束于第二个写操作。

请把上面的概念框架转换为可运行的C代码,实现临界区的保护。

为了加快程序的执行速度,可在阻塞循环中增加一个Sleep(0)语句。

这可以让不能进入临界区的线程马上放弃处理器,而不用无谓消耗处理器资源。

最后,请比较mutex方案和软件方案的效率(执行相同的循环次数,计算消耗的时间。

为了让结果更科学,请多次试验,然后计算平均值)。

提示:

时间度量可以用

DWORDGetTickCount(VOID)

在操作开始之前调用一次,操作结束之后再调用一次,两次调用所得到的返回值的差便是该操作所消耗的大致时间(单位毫秒)。

3、实验代码、数据及处理结果

2.1进程/线程并发执行

#include"stdafx.h"

int_tmain(intargc,_TCHAR*argv[])

{

return0;

}

#include

#include

#include

intaccnt1=0;

intaccnt2=0;

DWORDWINAPIrun(LPVOIDp){

intcounter=0;

inttmp1,tmp2,r;

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2-r;

counter++;

}while(accnt1+accnt2==0);

printf("循环1次数为%d\n",counter);

printf("%d,%d\n\n",accnt1,accnt2);

return0;

}

intmain(intargc,char∗argv[])

{

CreateThread(NULL,0,run,NULL,0,NULL);

CreateThread(NULL,0,run,NULL,0,NULL);

system("PAUSE");

return0;

}

由运行结果可观察出,当没有任何线程同步机制时,程序无法循环多次。

原因是没有线程同步机制。

2.21mutex方案

#include"stdafx.h"

int_tmain(intargc,_TCHAR*argv[])

{

return0;

}

#include

#include

#include

intaccnt1=0;

intaccnt2=0;

doublebegin=0;

doubleend=0;

doubletime=0;

inta=1;

HANDLEhMutex=CreateMutex(NULL,FALSE,NULL);

DWORDWINAPIrun(LPVOIDp){

intcounter=0;

inttmp1,tmp2,r;

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2-r;

counter++;

}while(accnt1+accnt2==0&&counter<1000000);

printf("循环%d次数为%d\n",a,counter);

printf("%d,%d\n\n",accnt1,accnt2);

end=GetTickCount();

time=end-begin;

printf("进程%d所用时间为%d\n",a,time);

a++;

ReleaseMutex(hMutex);

counter=0;

return0;

}

intmain(intargc,char∗argv[])

{

CreateThread(NULL,0,run,NULL,0,NULL);

CreateThread(NULL,0,run,NULL,0,NULL);

system("PAUSE");

return0;

}

由运行结果可观察出,当采用mutex方法时,两进程所运行的时间大致是相同的,进程运行完全,有效地防止了两进程相互交叉以及障碍。

2.22

#include"stdafx.h"

int_tmain(intargc,_TCHAR*argv[])

{

return0;

}

#include

#include

#include

intaccnt1=0;

intaccnt2=0;

DWORDWINAPIrun1(LPVOIDp){

intcounter=0;

inttmp1,tmp2,r;

doublebegin=0,end=0,time=0;

begin=GetTickCount();

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2-r;

counter++;

}while(accnt1+accnt2==0&&counter<1000000);

printf("循环次数为%d\n",counter);

printf("%d,%d\n\n",accnt1,accnt2);

end=GetTickCount();

time=end-begin;

printf("进程1所用时间为%d\n",time);

counter=0;

return0;

}

DWORDWINAPIrun2(LPVOIDp){

intcounter=0;

inttmp1,tmp2,r;

doublebegin=0,end=0,time=0;

begin=GetTickCount();

do{

tmp1=accnt1;

tmp2=accnt2;

r=rand();

accnt1=tmp1+r;

accnt2=tmp2-r;

counter++;

}while(accnt1+accnt2==0&&counter<1000000);

printf("循环次数为%d\n",counter);

printf("%d,%d\n\n",accnt1,accnt2);

end=GetTickCount();

time=end-begin;

printf("进程2所用时间为%d\n",time);

counter=0;

return0;

}

intmain(intargc,char∗argv[])

{

boolc1=false,c2=false;

intwillwait;

while

(1);

{

c1=true;

willwait=1;

while(c1&&(willwait=1))

{

CreateThread(NULL,0,run1,NULL,0,NULL);

break;

}

c1=0;

break;

}

while

(1);

{

c2=true;

willwait=2;

while(c2&&(willwait=2))

{

CreateThread(NULL,0,run2,NULL,0,NULL);

break;

}

c2=0;

break;

}

system("PAUSE");

return0;

}

由运行结果可观察出,该步骤并不能使进程解锁。

由于前后两次结果有执行到最后的也有迅速调试出结果的,因此该做法并不稳定。

四、实验体会或对改进实验的建议

将OS中引入进程可以提高了资源的利用率和系统的吞吐量,但是同时也会给系统造成混乱。

进程同步是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。

mutex机制实现了由一个进程对公共资源进行访问的时候,不允许其它进程对此资源进行访问,它保证了进程之间的互斥性。

 

南昌大学实验报告

学生姓名:

郭慧学号:

6100512019专业班级:

电子商务121班

实验类型:

□验证□综合□设计□创新实验日期:

2014-5-23实验成绩:

实验2编程实现银行家安全算法

一、实验目的

死锁会引起计算机工作僵死,因此操作系统中必须防止。

本实验的目的在于让学生独立的使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解死锁产生的条件和原因,并采用银行家算法有效地防止死锁的发生,以加深对课堂上所讲授的知识的理解。

二、实验要求

设计有n个进程共享m个系统资源的系统,进程可动态的申请和释放资源,系统按各进程的申请动态的分配资源。

系统能显示各个进程申请和释放资源,以及系统动态分配资源的过程,便于用户观察和分析;

四、实验步骤

1、分析银行家算法结构;

2、画出银行家算法的流程图,即设计说明;

3、根据画出的流程图使用C语言编写相应的代码

4、检查代码,将编出的代码编译、链接,验证其正确性。

五、算法流程、实验代码和实验结果

#include"stdafx.h"

int_tmain(intargc,_TCHAR*argv[])

{

return0;

}

#include

usingnamespacestd;

#defineFalse0

#defineTrue1

intMax[100][100]={0};

intAllocation[100][100]={0};

intNeed[100][100]={0};

intAvailable[100]={0};

intWork[100]={0};

charname[100]={0};

inttemp[100]={0};

intS=100,P=100;

intsafequeue[100]={0};

intRequest[100]={0};

//

voidShowdata()

{

inti,j,k,l;

cout<<"\t资源分配情况\n"<

cout<<"\tMax"<<"\t已分配"<<"\tNeed"<

cout<<"\t";

for(j=0;j<3;j++)

{

for(i=0;i

{

cout<

}

cout<<"\t";

}

cout<

for(i=0;i

{

cout<

for(j=0;j

{

cout<

}

cout<<"\t";

for(k=0;k

{

cout<

}

cout<<"\t";

for(l=0;l

{

cout<

}

cout<

}

cout<<"\nAvailable"<

for(i=0;i

{

cout<

}

cout<

for(i=0;i

{

cout<

}

cout<

}

intJudgesafe()

{

inttempwork[100][100]={0};

inti,x,k=0,m,apply,Finish[100]={0};

intj;

intflag=0;

for(i=0;i

{

Work[i]=Available[i];

}

for(i=0;i

{

apply=0;

for(j=0;j

{

if(Finish[i]==False&&Need[i][j]<=Work[j])

{

apply++;

if(apply==S)

{

for(m=0;m

{

tempwork[i][m]=Work[m];

Work[m]=Work[m]+Allocation[i][m];

}

Finish[i]=True;

temp[k]=i;

i=-1;

k++;

flag++;

}

}

}

}

for(i=0;i

{

if(Finish[i]==False)

{

cout<<"系统不安全"<

return-1;

}

}

cout<<"系统是安全的"<

cout<<"分配的序列:

";

for(i=0;i

{

cout<

if(i";

}

cout<

return0;

}

voidChangedata(intflag)

{

for(inti=0;i

{

Available[i]=Available[i]-Request[i];

Allocation[flag][i]=Allocation[flag][i]+Request[i];

Need[flag][i]=Need[flag][i]-Request[i];

}

}

//

voidShare()

{

inti,flag;

charch='Y';

cout<<"输入请求资源的进程:

"<

cin>>flag;

if(flag>=P)

{

cout<<"此进程不存在!

"<

}

else

{

cout<<"输入此进程对各个资源的请求数量:

"<

for(i=0;i

{

cin>>Request[i];

}

for(i=0;i

{

if(Request[i]>Need[flag][i])

{

cout<<"进程"<

"<

cout<<"分配不合理不予分配!

"<

ch='N';

break;

}

elseif(Request[i]>Available[i])

{

cout<<"进程"<

"<

cout<<"分配不合理,不予分配!

"<

ch='N';

break;

}

}

if(ch=='Y')

{

Changedata(flag);

if(Judgesafe()==-1)

{

cout<<"进程"<

"<

for(inti=0;i

{

Available[i]=Available[i]+Request[i];

Allocation[flag][i]=Allocation[flag][i]

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2