操作系统实验报告.docx
《操作系统实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统实验报告.docx(26页珍藏版)》请在冰豆网上搜索。
操作系统实验报告
实验一:
几种操作系统的界面
一.目地和要求
(一)目的
本实验的目的是使学生熟悉1-2种操作系统的界面,在熟练使用机器的基础上,能了解各种命令和调用在系统中的大致工作过程。
也就是通过操作系统的外部特征,逐步深入到操作系统的内部实质内容中去。
(二)要求
1.能熟练的在1-2种操作系统的环境下工作,学会使用各种命令,熟悉系统提供的各种功能,主动而有效地使用计算机。
2.熟悉系统实用程序的调用方法和各种系统调用模块的功能和作用。
二.内容
在某种操作系统的环境下建立,修改,运行,打印源程序和结果,最后撤销一个完整的程序。
提示:
可按下述步骤进行
1.编写一个完整的源程序,通过编辑命令送入机器,建立源程序文件;
2.编译该源文件,建立相应的目标文件;
3.编译有错时,再用编命令修改源文件,消除全部词法和语法错误;
4.连接目标文件,形成可执行文件;
5.执行该文件,形成可执行文件;
6.打印输出源程序和运行结果;
7.撤销本次实验中形成的所有文件。
三.实验过程
如下截图是我先用记事本编辑一段Java源程序,保存类型以.java为后缀。
然后在DOS环境下调用javac命令对程序进行的编译运行。
部分截图如下:
四.心得体会
这个实验我用到了JAVA程序和DOS命令调用,在DOS环境下运行JAVA程序时需要配置环境变量,这个步骤一定要很仔细,不然系统不识别命令,导致程序无法编译运行。
在程序编辑运行过程中,由于命名错误,以及单词拼写错误导致无法编辑。
程序编译通过时生成了一个.class文件。
相对现在编程的集成开发工具来说,用DOS调用命令比较麻烦,繁琐,如果单词记不住的话这是件很难的事。
我运行的这个只是很小的程序,很简单,如果碰到很大的程序的话需要花费的时间会比较多,修改错误时也会很麻烦。
不过DOS命令提示的问题错误很具体,方便程序员修改。
实验二进程调度设计
一、目的和要求
(一)目的
进程是操作系统最重要的概念之一,进程调度室操作系统的主要内容,本实验要求学生独立的用高级语言编写一个进程调度程序,调度算法可任意选或自行设计,本实验可使学生加深对进程调度和各种调度算法的理解。
(二)要求
1、设计一个有几个进程共行的进程调度程序,每个进程由一个进程控制块表示,进程控制
块通常包括以下信息:
进程名,进程优先数,进程需要运行时间,占用cpu的时间及进程状态等,且可按照调度算法的不同增删。
2、调度程序应包含2——3种不同的调度算法,运行时可以任选一种,以利于各种方法的
分析比较。
3、系统能显示或打印各进程状态的参数变化情况,便于观察。
二、实验内容
(1)优先算法。
进程就绪链按优先数大小从大到小排列,链首进程首先投入运行。
每过一个时间片,运行进程所需运行的时间片数减1,说明他已经运行了一个时间片,优先数也减3.。
理由是该进程如果在一个时间片完成不了,优先级应降低一级。
接着比较现行进程和就绪链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续运行,否则,调度就绪链首进程投入运行。
原运行进程在按其优先数大小插入就绪连,且改变他们对应的进程状态,直至所有进程都运行完各自的时间片数。
(2)简单轮转法。
进程就绪链按各进程进入的先后次序排列,进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相应于优先数法的优先级数记录项位置)。
每过一个时间片,运行进程占用处理机的时间片数加1,然后比较占用处理机的时间片数是否与该进程轮转片数相等,若相等说明以及达到轮转时间,应将现运行进程排到就绪链尾,调度链首进程占用处理机,且改变他们的进程状态,直至所有进程完成各自的时间片。
三、实验过程
#include
#include
#definefurthest5
structprocess
{intid;
intpriority;
intcputime;
intalltime;
charstate;
intnext;}
prochain[furthest];
intprocnum;
intrand();
intalgo;
intrun,head,tail,j;
main()/*MAINPROGRAM*/
{agan:
printf("typethealgorithmis(1:
RR,2:
PRIO):
");
scanf("%d",&algo);
if(algo==2)
{printf("outputofpriority.\n");
init();
prisch();}
else
{if(algo==1)
{printf("outputofroundrobin.\n");
init();
timesch();}
else
{printf("tryagain,please\n");
gotoagan;}
}
for(j=1;j<=40;j++)
{printf("=");}
printf("\n\n");
for(j=1;j<=40;j++)
{printf("=");}
printf("\n\n");
printf("systemfinished\n");}
print()/*PRINTTHERUNNINGPROCESS,WAITINGQUEUEANDPCBSEQUENCELIST*/
{intk,p;
for(k=1;k<=40;k++)
printf("=");
printf("\nrunningproc.");
printf("waitingqueue.");
printf("\n%d",prochain[run].id);
p=head;
while(p!
=0)
{printf("%5d",p);
p=prochain[p].next;}
printf("\n");
for(k=1;k<=40;k++)
printf("=");
printf("\n");
printf("id");
for(k=1;kprintf("%5d",prochain[k].id);
printf("\n");
printf("priority");
for(k=1;kprintf("%5d",prochain[k].priority);
printf("\n");
printf("cputime");
for(k=1;kprintf("%5d",prochain[k].cputime);
printf("\n");
printf("alltime");
for(k=1;kprintf("%5d",prochain[k].alltime);
printf("\n");
printf("state");
for(k=1;kprintf("%5c",prochain[k].state);
printf("\n");
printf("next");
for(k=1;kprintf("%5d",prochain[k].next);
printf("\n");
system("pause");
}
insert(q)/*INSERTAPROCESS*/
{intp,s;
p=head;
s=prochain[head].next;
while((prochain[q].priority=0))
{p=s;
s=prochain[s].next;}
prochain[p].next=q;
prochain[q].next=s;
}
insert2()/*PUTAPROCESSONTOTHETAILOFQUEUE*/
{prochain[tail].next=run;
tail=run;
prochain[run].next=0;
}
init()/*CREATEAWAITINGQUEUE*/
{inti;
head=0;
if(algo==2)
{for(i=1;i{prochain[i].id=i;
prochain[i].priority=(rand()+11)%41;
prochain[i].cputime=0;
prochain[i].alltime=(rand()+1)%7;
prochain[i].state='W';
prochain[i].next=0;
if((prochain[i].priority=0))
insert(prochain[i].id);
else
{prochain[i].next=head;
head=prochain[i].id;}
}
}
else
{for(i=1;i{prochain[i].id=i;
prochain[i].priority=(rand()+1)%3+1;
prochain[i].cputime=0;
prochain[i].alltime=(rand()+1)%7;
prochain[i].state='W';
prochain[i].next=(i+1)%(furthest+1);}
head=1;
tail=furthest;
prochain[furthest].next=0;
}
run=head;
prochain[run].state='R';
head=prochain[head].next;
prochain[run].next=0;
print();
}
prisch()/*THEPROCESSWITHPRIOALGORITHM*/
{while(run!
=0)
{prochain[run].cputime+=1;
prochain[run].priority-=3;
prochain[run].alltime-=1;
if(prochain[run].alltime==0)
{prochain[run].state='F';
prochain[run].next=0;
if(head!
=0)
{run=head;
prochain[run].state='R';
head=prochain[head].next;}
else
{prochain[0].id=prochain[run].id;
run=0;}
}
else
{if((prochain[run].priority=0))
{prochain[run].state='W';
insert(run);
run=head;
prochain[run].state='R';
head=prochain[head].next;}
}
print();
}
}
timesch()/*THEPROCESSWITHRRALRORITHM*/
{while(run!
=0)
{prochain[run].alltime-=1;
prochain[run].cputime+=1;
if(prochain[run].alltime==0)
{prochain[run].state='F';
prochain[run].next=0;
if(head!
=0)
{run=head;
prochain[run].state='R';
head=prochain[head].next;}
else
{prochain[0].id=prochain[run].id;
run=0;}
}
else
{if(head!
=0)
{prochain[run].state='W';
insert2();
run=head;
prochain[run].state='R';
head=prochain[head].next;}
}
print();
}
}
程序结果部分截图如下:
优先数法截图(显示方式从左到右)
简单轮转法截图(显示方式从左到右)
四、心得体会
这个实验的优先调度算法是抢占式优先权调度算法,在这种方式下,系统把处理机分配给优先权最高的进程,使之执行,但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。
在时间片轮转法中,时间片的轮转的大小对系统性能有很大的影响,如选择很小的时间片将有利于短作业,因为它能较快的完成,但会频繁的发生中断、进程上下文的切换,从而增加系统的开销;反之,如选择太长的时间片,使得每个进程都能在一个时间片内完成,时间片轮转算法便退化为FCFS算法,无法满足交互式用户的需求。
一个较为可取的大小是,时间片略大于一次典型的交互所需要的时间。
这样可使大多数进程在一个时间片内完成。
实验三存储管理
一.目的和要求
(一)目的
存储管理的主要功能之一是合理地分配空间。
请求页式管理是一种常用的虚拟存储管理技术。
本实验的目的是通过请求页式存储管理中页面置换算法的模拟设计,来了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。
(二)要求
模拟页式虚拟存储管理中硬件的地址转换和缺页中断,并用先进先出调度算法(FIFO)处理缺页中断。
二.提示
(1)为了装入一个页面而必须调出一页时,如果被选中调出的页面在执行中没有修改过,则不必把该页重新写到磁盘上(因磁盘上已有副本)。
因此,在页表中可以增加是否修改过的标志,当执行“存”指令、“写”指令时把对应页的修改标志置成“1”表示该页修改过,否则为“0”表示该页未修改过。
页表格式如3-1所示。
页号
标志
主存块号
修改标志
磁盘上的位置
表3-1页表格式
(2)设计一个地址转换程序来模拟硬件的地址转换和缺页中断。
当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可用输出转换后的绝对地址来表示一条指令已完成。
当访问的页不在主存时则输出“*该页页号”来表示硬件产生了一次缺页中断。
模拟地址转换的程序流程如图3-1所示。
见附录
(3)编制一个FIFO页面调度程序。
FIFO页面调度算法总是先调出作业中最先进入主存的那一页,因此,可以用一个数组来构成页号队列。
数组中每个元素是该作业已在主存的页面号,假定分配给作业的主存块数为m,且该作业开始的m页已装入主存,则数组可由m个元素组成:
P[0],P[1],…,P[m-1]
它们的初值为
P[0]:
=0,P[1]:
=1,…,P[m-1]:
=m-1
用一指针k指示当要装入新页时应调出的页在数组的位置,k的初值为“0”。
当产生缺页中断后,操作系统总是选择P[k]所指出的页面调出,然后执行
P[k]:
=要装入的新页页号
k:
=(k+1)modm
在试验中不必实际地启动磁盘执行调出一页和装入一页的工作,而用输出“OUT调出的页号”和“IN要装入的新页页号”来模拟一次调出和装入的过程。
模拟程序的流程见图3-1.
(4)假定主存的每块长度为1024个字节,现有一个共7页的作业,其副本已在磁盘上。
系统为该作业分配了4块主存块,且该作业的第0页至第3页已经装入主存,其余3页尚未装入主存,该作业的页表见表3-2.
表3-2作业的页表
页号
标志
主存块号
修改标志
在磁盘上的位置
0
1
5
0
011
1
1
8
0
012
2
1
9
0
013
3
1
1
0
021
4
0
0
022
5
0
0
023
6
0
0
121
如果该作业依次执行的指令序列如表3-3所示。
表3-3作业依次执行的指令序列
操作
页号
页内地址
操作
页号
页内地址
-
0
070
移位
4
053
-
1
050
-
5
023
*
2
015
存
1
037
存
3
021
取
2
078
取
0
056
-
4
001
-
6
040
存
6
084
依次执行上述的指令序列来调试你所设计的程序(仅模拟指令的执行,不必考虑指令序列中具体操作的执行)。
(5)为了检查程序的正确性,可自行确定若干组指令序列,运行设计的程序,核对执行的结果。
三、实验过程
#include"stdio.h"
charfind(intj);
intfindo(intj);
intl(intj);
intqueye;
doublequeyelu;
charz='%';
chara[4][20]={'7','0','1','2','0','3','0','4','2','3','0','3','2','1','2','0','1','7','0','1'};
voidfifo()
{inti=2,m,j;
queye=1;
a[1][0]=a[0][0];
for(j=1;j<20;j++)
{
if(i>3)i=1;
if(find(j)=='F')
{a[i][j]=a[0][j];
for(m=1;m<4;m++)
{if(m!
=i)a[m][j]=a[m][j-1];}
queye=queye+1;
i=i+1;
}
else
{
a[1][j]=a[1][j-1];
a[2][j]=a[2][j-1];
a[3][j]=a[3][j-1];
}}
for(i=0;i<4;i++)
{
for(j=0;j<20;j++)
{
printf("%c",a[i][j]);
}
printf("\n");}
queyelu=queye*100/20;
printf("缺页率:
%4.1f%c\n",queyelu,z);
}
charfind(intj)
{
if(j>=3&&(a[0][j]==a[1][j-1]||a[0][j]==a[2][j-1]||a[0][j]==a[3][j-1]))
return('T');
else
return('F');}
voidopt()
{inti,j,m,t;
a[1][0]=a[0][0];
for(j=1;j<3;j++)
{
for(i=1;i{if((i-j)==1)
a[i][j]=a[0][j];
else
a[i][j]=a[i][j-1];
}}
queye=3;
for(j=3;j<20;j++)
{
if(find(j)=='F')
{
t=findo(j);
for(m=1;m<4;m++)
{if(m!
=t)a[m][j]=a[m][j-1];}
a[t][j]=a[0][j];
queye=queye+1;
}
else{
a[1][j]=a[1][j-1];
a[2][j]=a[2][j-1];
a[3][j]=a[3][j-1];
}}
for(i=0;i<4;i++)
{
for(j=0;j<20;j++)
{
printf("%c",a[i][j]);
}
printf("\n");
}
queyelu=queye*100/20;
printf("缺页率:
%4.1f%c\n",queyelu,z);
}
intfindo(intj)
{
intx=21,y=21,z=21,m,t;
for(m=19;m>j;m--)
{
if(a[1][j-1]==a[0][m])x=m;
if(a[2][j-1]==a[0][m])y=m;
if(a[3][j-1]==a[0][m])z=m;
}
t=1;
if(y>x&&y>z)t=2;
if(z>x&&z>y)t=3;
return(t);
}
voidlru()
{intu,j,i;
intk;
a[1][0]=a[0][0];
for(j=1;j<3;j++)
{for(i=1;i{if((i-j)==1)
a[i][j]=a[0][j];
else
a[i][j]=a[i][j-1];
}}
queye=3;
for(j=3;j<20;j++)
{
if(find(j)=='T')
{
u=l(j);
k=2;
for(i=3;i>0;i--)
{
if(i!
=u)
{a[k][j]=a[i][j-1];
k=k-1;
}
}
a[3][j]=a[0][j];
}
else
{
for(i=1;i<3;i++)
{
a[i][j]=a[i+1][j-1];
}
a[3][j]=a[0][j];
queye=queye+1;
}
}
for(i=0;i<4;i++)
{
for(j=0;j<20;j++)
{
printf("%c",a[i][j]);
}
printf("\n");
}
queyelu=queye*100/20;
printf("缺页率:
%4.1f%c\n",queyelu,z);
}
intl(intj)
{
if(a[0][j]==a[1][j-1])return
(1);
if(a[0][j]==a[2][j-1])return
(2);
if(a[0][j]==a[3][j-1])return(3);
}
voidmain()
{
printf("先进先出算法:
\n");
fifo();
printf("最佳置换OPT算法:
\n");
opt();
printf("LRU算法:
\n");
lru();
getch();
}
四、心得体会
这个实验又加深了对页面置换算法的认识,他们的基本思想是:
最佳算法(OPT):
从主存移出永远不再需要的页面,若无这