3《操作系统原理》实验指导书

《操作系统原理》

课程实验指导书

(适用于网络工程专业)

网络工程系

辽宁工程技术大学软件学院

       

目   录

实验一  进程同步与互斥......................... 1

实验二  银行家算法实现资源分配................. 4

实验三  调度算法的使用......................... 6

实验四  请求页式存储管理....................... 9

实验五  文件管理实验.......................... 12

实验一进程同步与互斥

一、实验目的

1.掌握基本的同步与互斥算法,理解生产者消费者模型。

2.学习使用Windows 2000/XP中基本的同步对象,掌握相关API的使用方法。

3.了解Windows 2000/XP中多线程的并发执行机制,实现进程的同步与互斥。

二、实验内容

以生产者/消费者模型为依据,在Windows 2000环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。

三、实验性质

验证性实验

四、实验学时

2学时

五、实验环境

《C与C++程序设计学习与实验系统 》

六、实验原理及步骤

假设这些生产者和消费者相互是等效的,只要缓冲区不满,生产者便可将产品放入缓冲区;而只要缓冲区不为空,消费者便可从缓冲区取走一件产品。需要两个私用信号量,empty表示缓冲区可接收产品的数目,full表示缓冲区已接收产品的数目。empty的初值为N,即缓冲区的容量;full的初值为0。我们还要增设一个公用信号量(mutex),初值为1,以保证这些生产者和消费者互斥地访问缓冲区。此外,生产者和消费者必须同步,生产者不能向满缓冲区写数据,消费者不能从空缓冲区读数据。

1.测试用例文件

测试用例文件用于描述各线程的有关信息,该文件内容及格式如下:

3

1  P  3

2  P  4

3  C  4  1

4  P  2

5  C  3  1  2  4

说明:第一行给出的是程序中设置的临界区个数;其余各行是各进程信息。

      每行中的数据之间用Tab键分隔。

      第一列(除第一行外):线程号。

      第二列:P——生产者,C——消费者。

      第三列:线程在生产和消费前的休眠时间,单位为秒。

      第四及以后各列:消费的产品所对应的生产者线程号。

2.数据结构

(1) 用整型数组Buffer_Critical表示缓冲区。

(2) 用自定义结构ThreadInfo记录一条线程信息,多个线程对应一个ThreadInfo数组。

(3) 通过如下同步对象实现互斥:

l  设一个互斥量h-mutex,实现生产者在查询和保留缓冲区的下一个空位置时进行互斥。

l  设置h_Semaphore[MAX_THREAD_NUM]信号量数组表示相应产品已经生产,实现生产者与消费者之间的同步。同时,用表示空缓冲区树木的信号量empty_semephore指示是否存在空位置,实现类似的同步,以便开始下一个产品的生产。

l  设置临界区对象数组PC_Critical[MAX_BUFFER_NUM]实现每个缓冲区上消费者之间的互斥。

3.程序结构

    为了方便,程序结构用如下的文字予以描述。

        (1) 主函数

        (2) 初始化缓冲区、消费请求队列及部分同步对象

        (3) 提取线程信息

        (4) 完成线程相关同步对象的初始化

        (5) 创建线程,模拟生产者和消费者

        (6) 等待所有线程结束

        (7) 程序结束

        (8) 消费者

        (9) 有无消费请求?有,则继续(10);无,则转(16)

        (10) 此请求可满足?可满足,转(11);否,则阻塞,再转(10)

        (11) 确定产品位置

        (12) 此产品正被消费?是,则阻塞,再转(12);否,则转(13)

        (13) 进入临界区(请求同一产品的消费者之间互斥)

        (14) 消费产品,并判断是否应该释放产品所占缓冲区

        (15) 退出临界区,转(9)

        (16) 结束消费者线程

        (17) 生产者

        (18) 存在空缓冲区?有,则继续(19);无,则阻塞,再转(18)

        (19) 另一生产者在写?否,则转(20);是,则阻塞,再转(19)

        (20) 进入临界区(请求同一产品的生产者之间互斥)

        (21) 在缓冲区中为本线程产品分配空间

        (22) 退出临界区

        (23) 写入产品到分配的缓冲区空间中

        (24) 结束生产者线程

七、实验报告内容

1.实验的程序源码

2.运行程序,给出运行结果截图

3.分析实验结果,得出结论

实验二  银行家算法实现资源分配

一、实验目的

在了解和掌握银行家算法的基础上,能熟练的处理课本例题中所给状态的安全性问题,能编制银行家算法通用程序,将调试结果显示在计算机屏幕上,再检测和笔算的一致性。

二、实验内容

设计五个进程{P0,P1,P2,P3,P4}共享三类资源{A,B,C}的系统,{A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。

三、实验性质

验证性实验

四、实验学时

2学时

五、实验环境

《C与C++程序设计学习与实验系统 》

六、实验原理及步骤

1.进程pi提出资源申请时,系统执行下列步骤:

(1)若Request[i]≤Need[i],转(2);

            否则错误返回

(2)若Request[i]≤Available,

            转(3);否则进程等待

(3)假设系统分配了资源,则有:

Available:=Available-Request[i];

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

Need[i]:=Need[i]-Request[i]

(4)执行安全性算法,若系统新状态是安全的,则分配完成,若系统新状态是不安全的,则恢复原状态,进程等待

2.进行安全性检查,定义数据结构:

Work:ARRAY[0..m-1] of integer;

Finish:ARRAY[0..n-1] of Boolean;

m代表资源的数量,n代表进程的数量

(1) Work:=Available;

          Finish:=false;

(2) 寻找满足下列条件的i:

           a).  Finish[i]=false;

           b).  Need[i]≤Work;

                如果不存在,则转(4)

(3) Work:=Work+Allocation[i];

          Finish[i]:=true;

          转(2)

(4) 若对所有i,Finish[i]=true,则系统处于安全状态,否则处于不安全状态

设request­­i为进程p[i]的请求向量,如果requesti[j]=K,表示进程p[i]需要K个Rj资源。当系统发出请求后,系统按下述步骤开始检查:

(1)如果requesti[j]<=need[i][j],转向步骤2;否则报告出错,申请的资源已经大于它需要的最大值。

(2)如果requesti[j]<=available[j],转向步骤3;否则报告出错,尚无足够的资源。
       (3)系统试探着把资源分配给p[i],并修改下列数据结构中的值:

          available[j]=available[j]-request[j]

        allocation[i][j]=allocation[i][j]+request[j]

 need[i][j]=need[i][j]-request[j]

(4)系统进行安全性算法,检查此次分配后,系统是否还处于安全状态,若安全,把资源分配给进程p[i];否则,恢复原来的资源分配状态,让进程p[i]等待。

七、实验报告内容

1.实验的程序源码

2.运行程序,给出运行结果截图

3.分析实验结果,得出结论

实验三  调动算法的使用

一、实验目的

模拟单处理器系统的进程调度,采用动态优先权的进程调度算法作为进程设计算法,以加深对进程的概念及进程调度算法的理解。

二、实验内容

(1)用C语言实现对N个进程使用动态优先权算法的进程调度。

(2)描述用来标识进程的进程控制块PCB结构。

§   进程标识数ID

§   进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高(人为指定或随机数)。

§   进程已占用的CPU时间CPUTIME。

§   进程还需占用的CPU时间ALLTIME,当进程运行完毕ALLTIME是为0。 

§   进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,进程将进入阻塞状态。

§   进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后将转换成就绪状态。

§   进程状态STATE。

§   队列指针NEXT,用来将PCB排成队列。

(3)手工输入建立几个进程,建立一个就绪队列,按优先数由高到低排列。

(4)进行进程调度,进程调度流程如图1 所示。

(5)每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。

为了清楚的观察诸进程的调度过程,程序应将每个时间片内的进程的情况显示出来,参照的具体格式如下:

   RUNNING PROG: I

   READY_QUEUE:->id1->id2

   BLOCK_QUEUE:->id3->id4

三、实验性质

验证性实验

四、实验学时

4学时

五、实验环境

《C与C++程序设计学习与实验系统 》

六、实验原理及步骤

1. 启动C语言环境,新建文件。

2. 假设在调度前,系统中有5个进程,他们的初始状态如下:

ID               0     1     2     3     4

PRIORITY         9    38    30     29    0

CPUTIME          0     0     0     0     0

ALLTIME          3     3     6     3     4

STARTBLOCK       2    -1    -1     -1    -1

BLOCKTIME        3    0      0     0     0

STATE                 都为 READY

3.按照给定进程,作为程序的输入,编写程序运行。

七、实验报告内容

1.实验的程序源码

2.运行程序,给出运行结果截图

3.分析实验结果,得出结论

实验四   请求页式存储管理

一、实验目的

通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉虚存管理的各种页面淘汰算法。通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。

二、实验内容

(1)用C语言实现对分页式存储管理中的硬件的地址转换和产生缺页中断。

(2)设计页表。

分页式虚拟存储系统是把作业的副本存放在磁盘上,当作业被选中时,可把作业的开始几页先装入主存且启动执行。为此,在为作业建立页表时,应说明哪些页已在主存,哪些页尚未装入主存,页表的格式为:

(3)地址计算。

作业执行时,指令中的逻辑地址指出了参加运算的操作数存放的页号和单元号,硬件的地址转换机构按页号查页表,若该页对应标志为“1”,则表示该页已在主存,这时根据关系式:

                       绝对地址=块号*块长+单元号

计算出欲访问的主存单元地址。按计算出的绝对地址可以取到操作数,完成一条指令的执行。若访问的页标志为“0”,则表示该页不在主存,这时硬件发“缺页中断”信号,由OS按该页在磁盘上的位置,把该页信息从磁盘读出装入主存后再重新执行这条指令。

(4)设计“地址转换”程序模拟硬件的地址转换工作。

当访问的页在主存时,则形成绝对地址,但不去模拟指令的执行,而用输出转换后的地址来代替一条指令的执行。当访问的页不在主存时,则输出“*该页页号”,表示产生了一次缺页中断,执行缺页中断程序。该模拟程序的算法如图1.1所示。

 

图 1.1地址转换模拟流程图

(5) 缺页中断模拟

如果访问页不在主存且页表未满,则调入一页并打印页表情况;如果该页不在主存且页表已满,则产生缺页中断,模拟算法如图1.2所示。

  

图 1.2 缺页中断算法流程图

实验中采用FIFO算法进行页面淘汰。把在主存的页的页号按进入主存的先后次序排成队列,每次总是调出队首页。用数组存放页号的队列。若分配给该作业的物理块数为m,则数组由m个元素组成,p[0],p[1]……p[m-1],队首指针head,队尾指针tail。当装入新页时,将其页号装入数组。

三、实验性质

验证性实验

四、实验学时

2学时

五、实验环境

《C与C++程序设计学习与实验系统 》

六、实验原理及步骤

1. 启动C语言环境,新建文件。

2. 假定主存的每块长度为128个字节;现有一个共七页的作业,其中的第0页至第3页已经装入主存,其余三页未装入主存,主存;该作业的页表为:

如果作业依次执行的指令序列(操作,页号,单元号)为:

(+, 0, 070)、(+, 1, 050)、(*, 2, 015) 、(存, 3, 021)、(取, 0, 056)、(—, 6, 040)、(移位, 4, 053)、(+, 5, 023)、(存, 1, 037)、(取, 2, 078)、(+, 0, 070)、(+, 4, 001)、(存, 6, 084)。

运行设计的地址转换程序,显示或打印运行结果。因仅模拟地址转换,并不模拟指令的执行,故可不考虑上述指令序列中的操作。

3. 编写程序运行。

七、实验报告内容

1.实验的程序源码

2.运行程序,给出运行结果截图

3.分析实验结果,得出结论

实验五  文件管理实验

一、实验目的

文件系统是操作系统中管理取信息的机构,它具有“按名存取”的功能,不仅方便用户,而且能提高系统效率且安全可靠。

为了使学生对各种文件操作命令的实质内容和执行过程有深入了解,用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。

二、实验内容

1.内容:

(1) 设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。

(2) 程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)

(3)为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作.

2.要求:

模拟实现采用二级文件目录结构,第一级为主目录文件MFD,第二级为用户文件。目录文件UFD。

(1)设计一个有m个用户的文件系统,每个用户最多可保存一个文件;

(2)规定用户在一次运行中只能打开K个文件;

(3)系统能检查键入命令的正确性,出错时应能显示出错原因;

(4)对文件应能设置保护措施,如只能执行,允许读,允许写等;

(5)对文件的操作设计提供一套文件操作:

CREATE          建立文件

DELETE          删除文件

OPEN            打开文件

CLOSE           关闭文件

READ            读写文件

WRITE           写文件

3.二级目录结构

  

三、实验性质

验证性实验

四、实验学时

4学时

五、实验环境

《C与C++程序设计学习与实验系统 》

六、实验原理及步骤

1.文件系统算法的流程图如下:

2.程序示例

proram  fsystem(input,output);

   label   10;

   type

y=string[10]

links=^datas;

data=record

filename:y;

pcode:links;

length:integer;

end;

link=^dataf;

dataf=recod

     ue4rname:y;

     next:links;

     end;

linkf=^dataf;

dataf=record

     filename:y;

     opening:integer;

     next:linkt;

     end;

   var

mfd:array[1..5]of linkf;

pl,ql:linkf;

ufd.p2,q2:link;

x:y;

afd,p3,q3:linkt;

t:boolean;

r,l,I,l,k,n,s,m,j:integer;

procedure print;

begin

for I:=1to n do

    begin

    writeln(‘mfd-‘,mfd[I]^.username);

p2:=mfd[I]^next;

while p2<>nill do

    begin

    writeln(‘ufd-filename );

    writeln(p2^.filename:6,’-‘:6,p2^.pcode:6,p2^length:6);

    p2:=p2^next;

    end;

  end;

if i1<>0 then

   begin

   p3:=afd;

   while p3<>nil do

      begin

      writeln(‘afd-filename opening’);

      writeln(p3^.filename:6,’-‘:6,p3^. opening:6);

     p3:=p3^next;

    end;

  end;

end

procedure pcreate;

begin

writeln(‘create name=’);

readln(x);

q2:=ufdd;

while(q2^.filename<>x)and(q2^.next<>nil)do

   q2:=q2^.next;

if q2^.next=nil then

   begin

   new(p2);

   q2.next:=p2;

   p2^.filename:=x;

   write(‘create code=’);

   readln(m);

   p2^.fpcode:=m;

   write(create length=’);

   readln(s);

   p2^.length:=s;

   p2^.next:=nil;

   writeln(‘create finish’);

   print;

   endelse writeln(‘file has already been created’);

   end;

   procedure popen;

   begin

   p2:=ufd;

   write(‘input filename=’);

   readln(x);

   while(p2^.filename<>x)and(p2^.next<>nil)do

   p2:=p2^.next;

if p2^.filename=x then

   begin

   if i1<>0 then

   begin

   q3:=q3^.next;

   end;

end;

    if( q3^.filename=x )then

    writeln(‘the file is on the afd’)

else

   begin

   new(p3);

   if i1=0 then afd:=p3;

   else q3^.next:=p3;

   i1:=i1+1;

   p3^.filename:=x;

   p3^.opening:=i1;

   p3^.next:=nil;

   writeln(‘the file has been opend ,file number=’.i1);

   writeln;

   writeln;

   end;

end;

else write(‘error);

writeln;

print;

end;

procedure pcreate;

begin

write(‘the file name to be deleted=’);

readln(x);

writeln;

p3:=afd;q3:afd;

if p3^.filename<>x then

    begin

    q3:=p3;

    p3:=p3^.next;

    end;

if p3^.filename=x then

    begin

    q3^.next:=p3^.next;

    dispose(p3);

    end;

p2:=ufd;q2:ufd;

if p2^.filename<>x then

    begin

    while(p2^.filename<>x)and(p2^.next<>nil)do

        being

        q2:=p2;

        p2:=p2^.next;

        end;

if p2^.filename=xs then

    begin

    q2^.next:=p2^.next;

    dispose(p2);

    writeln(‘the file is deleted’)

    end;

else

    begin

    ufd:=p2^.next;

    dispose(p2);

    writeln(‘the file is deleted’)

    end;

print;

end;

procedure pclose;

var

j:integer;

begin

write(‘input close filename=’);

readln(x);q3:=afd;p3:=q3;j:=0;

while(q3^.filename<>x)and(q3^.next<>nil)do

being

        p3:=q3;

        q3:=p3^.next;

        end;

if(q3^.next<>nil)or(q3^.filename<>x)then

       begin

   p3^.next:=q3^.next;

   dispose(q3);

   writeln(‘end of close’);

   p3:=afd;

   while(p3^.next<>nil)do

   begin

   j:=j+1;p3:=p3^.next;

   end;

if j=0 then i1:=0;

writeln(‘afd file number=’.I);while

writeln;

end

else writeln(‘not retionnal’);

print;

end;

procedure pbye;

begin

p2:ufd;

writeln(‘ufd---filename ---pocde---length’);

while p2<>nil do

   begin

   write(p2^.filename:13);

   write(p2^.pocde:7,p2^.length:10);

   writeln;

   p2:=p2^.next;

   end;

write(‘the end of imiate    ‘);

writeln(‘1991.5’);

t:=ture;

end;

begin(*-----------------------main program---------------------------*)

write(‘user number n=’);

readln(n);

for i1:=1 to n do

   begin 

   write(‘uer mfd filename x’,I:22,’=’:=2);

   readln(x);

   new (mfd[I]);

   p1:=mfd[I];

   p1:=mfd[I];

   p1^.username:=x;

   p1^.next:=nil;

   write(‘input(‘,I:2,’)’);

   write(‘one uer file numbers k=’);

   readln(k);

   new(p2);

   for j:=1 to k do

      begin

      write(‘input     ufd--------name=’);

      readln(x);

      p2^.length;=s;

      p2^.next:=nil;

      ufd:=p2;  new(p2);

      ufd^.next:=p2;

      end;

   print;

writeln(‘input uer name you wantto opearate’);

   readln(x);I:=1;

   whilex<>mfd[I]^.uername do

      begin

      if i>=n then

         begin

         writeln(‘not found user mfd filename’);

         writeln(‘input again mfd filename’);

         goto 10

         end

      else

   i:=i+1;

   end;

ufd:=mfd[I]^.next;

t:=fale; i1:=0;

while t<>true do

   begin

   writeln(‘--------------------------------------------------------’);

   writeln(‘    1---create          2---open           ’);

       writeln(‘    3---delete          4---close           ’);

       writeln(‘    5---read           6--- write           ’);

       writeln(‘    7---end                              ’);

       writeln(‘---------------------------------------------------------’);

   readln(s);

       case s of

          1:pcreate;

          2:popen;

          3:pdelete;

          4:pclose;

          5:pread;

          6:pwrite;

          7:pbye;

       end;

    end.

七、实验报告内容

1.实验的程序源码

2.运行程序,给出运行结果截图

3.分析实验结果,得出结论

相关推荐