操作系统课设报告 本文关键词:操作系统,报告
操作系统课设报告 本文简介:[键入文字]操作系统课程设计操作系统课程设计报告时间:2013-1-7~2013-1-18地点:信息技术实验中心计算机科学与技术专业2010级01班06号赖敏2013-1-18目录一课程设计的目的和意义3二进程调度算法模拟31设计目的32设计要求33使用动态优先权的进程调度算法的模拟4三动态分区分配
操作系统课设报告 本文内容:
[键入文字]
操作系统课程设计
操作系统课程设计报告
时间:2013-1-7~2013-1-18
地点:信息技术实验中心
计算机科学与技术专业
2010级01班06号
赖敏
2013-1-18
目录
一
课程设计的目的和意义3
二
进程调度算法模拟3
1
设计目的3
2
设计要求3
3
使用动态优先权的进程调度算法的模拟4
三
动态分区分配方式模拟11
1
设计目的11
2
设计要求11
3
模拟算法的实现12
3.3.1
首次适应算法13
3.3.2
最佳适应算法13
四
请求调页存储管理方式模拟18
1
设计目的18
2
设计要求18
3
模拟算法的实现18
4.3.1OPT算法18
4.3.2FIFO算法21
4.3.3LRU算法22
五
简单文件系统的实现24
1
设计目的24
2
设计要求24
3
模拟算法的实现25
六
总结40
一
课程设计的目的和意义
操作系统课程设计是计算机科学与技术专业的重要实践性教学环节。在进行了专业基础课程和操作系统原理课程学习的基础上,设计或分析一个实际的操作系统旨在加深对计算机硬件结构和系统软件的认识,初步掌握操作系统组成模块和应用接口的使用方法,提高进行工程设计和系统分析的能力,为毕业设计及以后的工程实践打下良好的基础。
通过课程设计,加深对操作系统各资源管理模块的理解,掌握操作系统的基本原理及功能,具有初步分析实际操作系统、设计、构造和开发现代操作系统的基本能力
1、巩固和加深对操作系统原理的理解,提高综合运用本课程所学知识的能力。
2、培养学生选用参考书,查阅手册及文献资料的能力。培养独立思考,深入研究,分析问题、解决问题的能力。
3、通过实际操作系统的分析设计、编程调试,掌握系统软件的分析方法和工程设计方法。
4、能够按要求编写课程设计报告书,能正确阐述设计和实验结果、正确绘制系统和程序框图。
5、通过课程设计,培养学生严谨的科学态度,严肃认真的工作作风和团队协作精神。
二
进程调度算法模拟
1
设计目的
通过动态优先权算法的模拟加深对进程概念和进程调度过程的理解。
2
设计要求
(1)用C语言来实现对N个进程采用动态优先算法的进程调度;
(2)每个用来标识进程的进程控制块PCB用结构来描述,包括以下字段:
l
进程标识符id
l
进程优先数priority,并规定优先数越大的进程,其优先权越高;
l
进程已占用的CPU时间cputime;
l
进程还需占用的CPU时间alltime,当进程运行完毕时,alltime变为0;
l
进程的阻塞时间startblock,表示当进程再运行startblock个时间片后,进程将进入阻塞状态;
l
进程被阻塞的时间blocktime,表示已阻塞的进程再等待blocktime个时间片后,将转换成就绪态
l
进程状态state;
l
队列指针next,用来将PCB排成队列
(3)优先数改变的原则:
l
进程在就绪队列中呆一个时间片,优先数增加1
l
进程每运行一个时间片,优先数减3。
(4)假设在调度前,系统中有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
READY
READY
READY
READY
(5)为了清楚地观察诸进程的调度过程,程序应将每个时间片内的进程的情况显示出来,参照的具体格式如下:
RUNNING
PROG:
i
READY_QUEUE:->id1->id2
BLOCK_QUEUE:->id3->id4
==================================
ID
01234
PRIORITY
P0P1P2P3P4
CPUTIME
C0C1C2C3C4
ALLTIME
A0A1A2A3A4
STARTBLOCK
T0T1T2T3T4
BLOCKTIME
B0B1B2B3B4
STATE
S0S1S2S3S4
3
使用动态优先权的进程调度算法的模拟
(1)
流程图如图1.3.1:
N
Y
N
Y
N
Y
开始
创建N个进程并初始化pcb[N]
根据进程状态初始化阻塞队列和就绪队列
在就绪队列中找出优先权最大的进程运行
进程运行完毕即alltime=0
删除该进程
运行一个时间片
就绪队列中其他进程优先数prority+1
进程运行完毕
优先数priority-3
结束
阻塞就绪转换
进程调入就绪队列或阻塞队列
1.3.1-
动态优先权进程调度流程图
(2)
实验效果图:
1)输入进程的初始状态进行初始化如图1.3.2:
1.3.2-
初始化进程状态
2)运行部分结果如图1.3.3:
1.3.3-
运行结果
(3)实验关键代码:
#define
N
5
//默认进程数
int
count;
//定义进程结构体
typedef
struct
pcb{
int
id;
//进程id号
int
priority;
//进程优先权
int
cputime;
//占用cpu时间
int
alltime;
//进程运行完成时间
int
startblock;
//进程开始阻塞时间
int
blocktime;
//进程阻塞到恢复就绪时间
char
state;
//进程状态
pcb*
next;
//指向下一个进程指针
}pcb,*pcb_link;
//初始化进程
pcb_link
initTask(pcb
pcb[]){
int
i;
char
c;
pcb_link
plink=(pcb_link)malloc(sizeof(pcb));
//就绪队列创建头指针
plink->next=NULL;
printf(“请初始化%d个进程:/n“,N);
printf(“ID
“);
//初始化进程id
for(i=0;inext=
就绪队列
return
plink;/
}
//在就绪队列中找到优先数最大的进程
int
maxPriority(pcb_link
ready_q){
pcb_link
p;
p=ready_q->next;
int
prog,max;
max=prog=INT_MIN;
while(p){
if(p->priority>max){
prog=p->id;
max=p->priority;
}
p=p->next;
}
return
prog;
}
//进程运行函数
void
run(pcb_link
ready_q,pcb_link
block_q,int
prog){
pcb_link
p,running_p=NULL;
if(-1next;
while(p){
if(p->id==prog)
running_p=p;
//running_p指向运行的进程
else
p->priority+=1;
//就绪队列中其他进程priority+1
p=p->next;
}
running_p->priority-=3;
/*
running_p->cputime+=1;
running_p->alltime-=1;
if(running_p->startblock>0)
running_p->startblock-=1;
改变运行进程
if(running_p->alltime==0)
的信息和状态
running_p->state=
F
;
else
if(running_p->startblock!=0)
running_p->state=
R
;
else
running_p->state=
B
;/
}
p=block_q->next;
while(p){
p->blocktime-=1;
if(p->blocktime==0)
//判断阻塞队列中进程状态是否变成就绪状态
p->state=
R
;
p=p->next;
}
}
//进程调入或调出就绪队列函数
void
ready_or_block(pcb_link
ready_q,pcb_link
block_q,int
prog,pcb
pcb[]){
pcb_link
p,q,ready_end,block_end,t;
ready_end=block_end=t=NULL;
p=ready_q;
while(p->next)
p=p->next;
ready_end=p;
//就绪队列尾指针
q=block_q;
p=block_q->next;
while(p){
if(p->state==
R
){
t=p;
q->next=t->next;
/*
阻塞队列中就绪进程
t->next=ready_end->next;
插到就绪队列尾部
ready_end->next=t;/
ready_end=t;
//修改就绪队列尾指针
}
else
q=p;
p=q->next;
}
block_end=q;
if(prog>-1
if(pcb[prog].state==
B
){
/*
while(p->id!=prog
运行后进程变成阻塞状态
p=p->next;
插到阻塞进程尾部
}
q->next=p->next;
p->next=block_end->next;
block_end->next=p;
//修改阻塞队列尾指针/
}
else
if(pcb[prog].state==
R
){
while(p->id!=prog
p=p->next;
}
if(p->next){
q->next=p->next;
p->next=ready_end->next;
ready_end->next=p;
}
}
else{
/*
count++;
while(p->id!=prog
进程计数器count++
p=p->next;
并删除该进程
}
q->next=p->next;/
}
}
}
int
main(void){
pcb
pcb[N];
//创建进程数组
pcb_link
ready,block;
//创建就绪和阻塞队列头指针
int
program;
count=0;
//进程计数器初始为0
block=(pcb_link)malloc(sizeof(pcb));
block->next=NULL;
ready=initTask(pcb);
//初始化进程
printf(“/n/n/n运行过程:/n“);
while(count=tsk[task_id].size){
//找到第一个够分的空间块
free[i].size-=tsk[task_id].size;
tsk[task_id].workplace=i;
break;
}
if(i==free_block)
printf(“任务%d分配空间失败/n“,task_id);
//分配失败输出
}
//释放任务空间
void
fre(space
free[],task
tsk[],int
task_id){
int
work;
work=tsk[task_id].workplace;
free[work].size+=tsk[task_id].size;
//空间块空间增加
tsk[task_id].workplace=-1;
}
3.3.2
最佳适应算法
最佳适应算法(Best-fit):当要分配内存空间时,就查找空闲表中满足要求的空闲块,并使得剩余块是最小的。然后把它分配出去,若大小恰好合适,则直接分配;若有剩余块,则仍保留该余下的空闲分区,并修改分区大小的起始地址。
最佳适应算法和首次适应算法的不同之处是,在为进程分配和释放一个空间后对分区链表进行一次从小到大的排序。
算法代码如下:
//没分配完一个分区或进程释放空间,对分区链表进行排序
void
sort(space_link
slink){
space_link
tp,t,p,q;
tp=(space_link)malloc(sizeof(space));
//创建临时头指针,用来指向已排序的分区
tp->next=NULL;
t=slink->next;
slink->next=t->next;
t->next=tp->next;
tp->next=t;
t=slink->next;
while(t){
q=tp;
p=tp->next;
while(p){
if(t->size>p->size){
//找到待排序的分区在有序链表里的位置
q=p;
p=p->next;
}
else
break;
}
slink->next=t->next;
/*
t->next=p;
q->next=t;
插入有序链表
t=slink->next;/
}
slink->next=tp->next;
free(tp);
}
关键实验代码如下:
#define
free_block
5
//空闲分区块数
#define
free_space
640
//空闲分区总数
#define
N
7
//任务数
//定义分区块
typedef
struct
space{
int
id;
//分区块id
int
size;
//分区块大小
spacenext;
//指向下一个分区块
}space,*space_link;
//定义任务结构体
typedef
struct
task{
int
id;
//任务id
int
size;
//任务需要空间大小
int
workplace;
//申请到的空间块
}task,*task_link;
//初始化分区
space_link
init_space(space
free[]){
int
i,sum,a;
space_link
sh;
sum=0;
a=40;
//初始大小40
sh=(space_link)malloc(sizeof(space));
for(i=0;inext=/
return
sh;
//返回链表头指针
}
//初始化任务
void
init_task(task_link
tsk,int
task_id,int
size){
tsk->id=task_id;
tsk->size=size;
tsk->workplace=-1;
//申请到的空间块初始为-1
}
int
main(void){
space
spa[free_block];
task
tsk[N];
space_link
space_head;
char
c;
space_head=init_space(spa);
printf(“动态分区分配方式的模拟/n“);
printf(“亲输入分区方式,F用首次适应算法分配,B用最佳适应算法分配/n/n“);
printf(“请选择分配方式:“);
scanf(“%c“,printf(“/n/n“);
if(c==
F
){
//首次适应算法
init_task(
//初始任务0
alloc(spa,tsk,0);
//给任务0分配空间
print(space_head);
//输出分区状态
init_task(
alloc(spa,tsk,1);
print(space_head);
init_task(
alloc(spa,tsk,2);
print(space_head);
fre(spa,tsk,1);
//释放任务1空间
print(space_head);
init_task(
alloc(spa,tsk,3);
print(space_head);
fre(spa,tsk,2);
print(space_head);
fre(spa,tsk,0);
print(space_head);
init_task(
alloc(spa,tsk,4);
print(space_head);
init_task(
alloc(spa,tsk,5);
print(space_head);
init_task(
alloc(spa,tsk,6);
print(space_head);
fre(spa,tsk,5);
print(space_head);
}
else
if(c==
B
){
//最佳首次适应算法
init_task(
alloc(spa,tsk,0);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,1);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,2);
sort(space_head);
print(space_head);
fre(spa,tsk,1);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,3);
sort(space_head);
print(space_head);
fre(spa,tsk,2);
sort(space_head);
print(space_head);
fre(spa,tsk,0);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,4);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,5);
sort(space_head);
print(space_head);
init_task(
alloc(spa,tsk,6);
sort(space_head);
print(space_head);
fre(spa,tsk,5);
sort(space_head);
print(space_head);
}
}
运行结果图如图2.3.2:
2.3.2-
运行结果
四
请求调页存储管理方式模拟
1
设计目的
熟练掌握操作系统中请求调页方式的存储管理算法。
2
设计要求
1)
假设每个页面中可以存放10条指令,分配给一个作业的内存块数为4;
2)
用C语言模拟一作业的执行过程,改作业共320条指令,即其地址空间为32页,目前他的所有页还未调入内存。在模拟过程中,如果所访问的指令已经在内存,则显示其物理地址,并转到下一条指令,如果所访问指令还未装入内存,则发生缺页,此时需记录缺页的次数,并将相应页调入内存;如果4个内存块中均有内容,
则需进行页面置换;最后显示其物理地址,并转向下一条指令。在所有的320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。
3)
置换算法请分别采用OPT、FIFO和LRU;
4)
作业中的指令顺序按如下原则生成:
l
50%的指令顺序执行;
l
25%的指令跳转到当前地址前(目标地址随机生成);
l
25%的指令跳转到当前地址后(目标地址随机生成);
具体的实施方法是:
①
在[0,319]的指令地址之间随机选取一条起始执行指令,其序号为m;
②
顺序执行下一条指令,即序号为m+1的指令;
③
通过随机数跳转到前地址部分[0,m-1]中的某条指令处,其序号为;
④
顺序执行下一条指令,其地址为+1的指令;
⑤
通过随机数跳转到后地址部分[+2,319]中的某条指令处,其序号为;
⑥
顺序执行下一跳指令,即序号为+1的指令;
⑦
重复跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行的过程,直至执行320条指令。
3
模拟算法的实现
4.3.1
OPT算法
OPT算法关键代码如下:
void
opt(memory*m,pagepag[]){
int
i,j,m1,m2,m3,p,order_id,a[320][3],b[BLOCK_N]={-1,-1,-1,-1};//数组a用来存放320执行指令,数组b用来存放当前内存块中指令
count_order=i=j=0;
//初始化指令数组
for(j;j-1){
m2=random_order(0,m1-1);
//跳转到前地址指令
p=belong_page(m2);
order_id=belong_orderId(m2);
pag[p].ord[order_id].state=1;
a[i][0]=p;
a[i][2]=m2;
//存入数组a
//printf(“%d/n“,a[i][0]);
i++;
count_order++;
//指令计数器加1
}
if(m2+1block[m->point]==-1){
//内存块没有装满
pag[a[i][0]].workplace=m->point;
m->block[m->point]=a[i][0];
m->point=(m->point+1)%BLOCK_N;
//指向下一个内存块的位置
b[m->point]=a[i][2];
//数组b记录指令号
print(*m);
//输出内存块状态
printf(“/n“);
}
else{
//内存块已满,需置换
m2=-1;
for(j=0;jm2){
m2=a[m1][1];
m3=j;
//在数组b中找到需置换的指
}
}
order_id=b[m3];
p=belong_page(order_id);
//计算页号
m1=pag[p].workplace;
pag[p].workplace=-1;
//修改被置换页的状态
b[m3]=a[i][2];
//新指令替换原指令
m->block[m1]=a[i][0];
//内存块替换
pag[a[i][0]].workplace=m1;
//修改新指令的页状态
print(*m);
//输出内存状态
printf(“/n“);
}
count++;
//缺页数加1
}
else{
//页号在内存块中
for(j=0;jblock[m->point]==-1){
//内存块不满
pag[pg].workplace=m->point;
m->block[m->point]=pg;
m->point=(m->point+1)%BLOCK_N;
//指向下一个内存块
print(*m);
//输出内存块状态
}
else{
//内存块已满
pag[m->block[m->point]].workplace=-1;
//修改被替换页状态
pag[pg].workplace=m->point;
//修改指令所在页状态
m->block[m->point]=pg;
//新页存入内存块
m->point=(m->point+1)%BLOCK_N;
//指向下一个内存块
print(*m);
//输出内存状态
}
count++;
//缺页数加1
}
pag[pg].ord[id].state=1;
count_order++;
//指令计数器加1
}
}
4.3.3
LRU算法
void
lru(memory*m,int
order_id,page
pag[],stacks){
int
pg=belong_page(order_id);
//计算页号
int
id=belong_orderId(order_id);
//计算所在页的id
int
middle,i;
if(pag[pg].ord[id].state==0){
//指令未被执行
if(pag[pg].workplace==-1){
//页不在内存块中
if(m->block[m->point]==-1){
//内存块未满
m->block[m->point]=pg;
//页存入内存块
pag[pg].workplace=m->point;
//修改页状态
m->point=(m->point+1)%BLOCK_N;
//指向下一个内存块
s->st[s->top]=pg;
//页压入栈
s->top++;
//栈顶指针加1
print(*m);
//输出内存状态
}
else{
//内存已满
pag[pg].workplace=pag[s->st[s->bottom]].workplace;
//修改页状态
pag[s->st[s->bottom]].workplace=-1;
//修改被置换页状态
for(i=s->bottom;itop-1;i++)
s->st[i]=s->st[i+1];
s->st[i]=pg;
//栈顶存入新页
m->block[pag[pg].workplace]=pg;
print(*m);
}
count++;
//缺页数加1
}
else{
for(i=s->bottom;itop;i++)
if(s->st[i]==pg)
middle=i;
for(i=middle;itop-1;i++)
s->st[i]=s->st[i+1];
//修改栈中页的顺序
s->st[i]=pg;
}
pag[pg].ord[id].state=1;
count_order++;
//指令数加1
}
}
实验关键代码如下:
#define
ORDER_N
10
#define
PAGE_N
32
#define
BLOCK_N
4
int
count;
//缺页计数器
int
count_order;
//指令计数器
//定义指令结构体
typedef
struct
order{
int
id;
int
belong;
int
state;
}order;
//定义页结构体
typedef
struct
page{
order
ord[ORDER_N];
int
workplace;
}page;
定义内存结构体
typedef
struct
memory{
int
block[BLOCK_N];
int
point;
}memory;
//定义栈
typedef
struct
stack{
int
st[BLOCK_N];
i
篇2:计算机操作系统知识点总结重点题型答案
计算机操作系统知识点总结重点题型答案 本文关键词:知识点,题型,操作系统,答案,重点
计算机操作系统知识点总结重点题型答案 本文简介:计算机操作系统复习资料1.操作系统的定义操作系统(OperatingSystem,简称OS)是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便的、有效的、友善的服务界面。操作系统通常是最靠
计算机操作系统知识点总结重点题型答案 本文内容:
计算机操作系统复习资料
1.
操作系统的定义
操作系统(Operating
System,简称OS)是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便的、有效的、友善的服务界面。
操作系统通常是最靠近硬件的一层系统软件,它把硬件裸机改造成为功能完善的一台虚拟机,使得计算机系统的使用和管理更加方便,计算机资源的利用效率更高,上层的应用程序可以获得比硬件提供的功能更多的支持。
操作系统是一个庞大的管理控制程序,大致包括5个方面的管理功能:进程与处理机管理、作业管理、存储管理、设备管理、文件管理。
2.
操作系统的作用
1)
OS作为用户与计算机硬件系统之间的接口
2)
OS作为计算机系统资源的管理者
3)
OS实现了对计算机资源的抽象
3.
操作系统的基本特征
1)
并发
2)
共享
3)
虚拟
4)
异步
4.
分时系统的概念
把计算机的系统资源(尤其是CPU时间)进行时间上的分割,每个时间段称为一个时间片,每个用户依次轮流使用时间片,实现多个用户分享同一台主机的操作系统。
5.
分时系统要解决的关键问题(2个)
1)
及时接收
2)
及时处理
6.
并发性的概念
并发性是指两个或多个事件在同一事件间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时的交替执行。
7.
程序顺序执行的特征和并发执行的特征
顺序执行的特点:
顺序性
封闭性
可再现性
程序并发执行的特点:
1)、间断性(失去程序的封闭性)
2)、不可再现性
任何并发执行都是不可再现
3)、进程互斥(程序并发执行可以相互制约)
8.
进程的定义
进程是指在系统中能独立运行并作为资源分配的基本单位。
为了使参与并发执行的每个程序(含数据)都能独立的运行,在操作系统中必须为之配置一个专门的数据结构,称为进程控制块(PCB)。系统利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程。
9.
进程的组成部分
进程是由一组机器指令,数据和堆栈组成的,是一个能独立运行的活动实体。
由程序段,相关的数据段和PCB三部分便构成了进程实体(又称进程映像)。
10.
进程的状态(状态之间的变化)
就绪状态、执行状态、阻塞状态。
处于就绪状态的进程,在调度程序为之分配了处理机之后,该进程便可以执行,相应的,他就由就绪状态转变为执行状态。
正在执行的进程,如果因为分配给它的时间片已经用完而被暂停执行时,该进程便由执行状态又回到就绪状态;如果因为发生某事件而使进程的执行受阻(如进程请求访问临界资源,而该资源正在被其它进程访问),使之无法继续执行,该进程将有执行状态转变为阻塞状态。处于阻塞状态的进程,在获得了资源后,转变为就绪状态。
11.
进程同步的概念
进程同步是是并发执行的诸进程之间能有效地相互合作,从而使程序的执行具有可再现性,简单的说来就是:多个相关进程在执行次序上的协调。
12.
PV原语的作用
PV原语通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序。
13.
处理死锁的四种方法(有何不同)
1)
预防死锁。这是一种简单和直观的事先预防方法。该方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件(互斥条件,请求和保持条件,不可抢占条件,循环等待条件)中的一个或几个来预防产生死锁。预防死锁是一种较易实现的方法,已被广泛使用、
2)
避免死锁。同样是属于事先预防策略,但它并不是事先采取各种限制措施,去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而可以避免发生死锁。
3)
检测死锁。这种方法无须事先采取任何限制性措施,允许进程在运行过程中发生死锁。但可通过检测机构及时地检测出死锁的发生,然后采取适当的措施,把进程从死锁中解脱出来。
4)
解除死锁。当检测到系统中已发生死锁时,就采取相应措施,将进程从死锁状态中解脱出来。常用的方法是撤销一些进程,回收它们的资源,将它们分配给已处于阻塞状态的进程,使其能继续运行。
上述的四种方法,从1)到4)对死锁的防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程因资源因素而阻塞的频度下降(即并发程度提高)。
14.
解除死锁的方法
常采用解除死锁的两种方法是:
1)
抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态。
2)
终止(或撤销)进程。终止(或撤销)系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态解脱出来。
15.
死锁产生的必要条件
1)
互斥条件
2)
请求和保持条件
3)
不可抢占条件
4)
循环等待条件
16.
死锁的概念
如果一组进程中的每一个进程都在等待仅由该组进程中的其它进程才能引发的事件,那么该组进程是死锁的。
17.
银行家算法
银行家算法是一种最有代表性的避免死锁的算法。
要解释银行家算法,必须先解释操作系统安全状态和不安全状态。
安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。
安全序列
一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj
(j
1)在等待表演。只要钢丝上无人时便允许一名演员从钢丝的一端走到另一端。现要求两端的演员交替地走钢丝,且从A端的一名演员先开始。请问,把一名演员看作一个进程时,怎样用WAIT,SIGNAL操作来进行控制?请写出能进行正确管理的程序。
2.
有—阅览室,读者进入时必须先在一张登记表中进行登记,该表为每一座位列一表目,包括座号和读者姓名,读者离开时要消掉登记信息,阅览室中共有100个座位,试问:试用信号量和wait,signal原语写出这些进程间的同步算法。
3.
请用信号量解决以下的“过独木桥”问题:同一方向的行人可连续过桥,当某一方向有人过桥时,另一方向的行人必须等待;当某一方向无人过桥时,另一方向的行人可以过桥。
4.
假定系统有三个并发进程read,move和print共享缓冲器B1和B2。进程read负责从输入设备上读信息,每读出一个记录后把它存放到缓冲器B1中。进程move从缓冲器B1中取出一记录,加工后存入缓冲器B2。进程print将B2中的记录取出打印输出。缓冲器B1和B2每次只能存放一个记录。要求三个进程协调完成任务,使打印出来的与读入的记录的个数,次序完全一样。
请用WAIT()和SIGNAL()原语操作,写出它们的并发程序。
1、某虚拟存储器的用户编程空间共32个页面,每页为1KB,内存为16KB。假定某时刻一用户页表中已调入内存的页面的页号和物理块号的对照表如下:
页号
物理块号
0
5
1
10
2
4
3
7
则逻辑地址0A5C(H)所对应的物理地址是什么?
解:程序空间的大小为32KB,因此逻辑地址的有效位数是15位。内存储空间的大小是16KB,因此物理地址至少需要14位。
当页面为1KB时,虚地址0A5C表示页号为00010,页内地址是1001011100.该页在内存的第4块,即块号为0100,因此0A5C的物理地址是01001001011100,即123CH。
2、某段表内容如下:
段号
段首地址
段长度
0
120K
40K
1
760K
30K
2
480K
20K
3
370K
20K
一逻辑地址为(2,154)的实际物理地址为多少?
答:逻辑地址(2,154)表示段号为2,即段手地址为480K,154为单元号,则实际物理地址为480K+154。
3、考虑下述页面走向:
1,2,3,4,2,1,5,6,2,1,2,3,7,6,3,2,1,2,3,6
当内存块数量分别为3时,试问FIFO、LRU、OPT这三种置换算法的缺页次数各是多少?
答:缺页定义为所有内存块最初都是空的,所以第一次用到的页面都产生一次缺页。
当内存块数量为3时:
发生缺页中断的次数为16。
在FIFO算法中,先进入内存的页面被先换出。当页6要调入时,内存的状态为4、1、5,考查页6之前调入的页面,分别为5、1、2、4,可见4为最先进入内存的,本次应换出,然后把页6调入内存。
发生缺页中断的次数为15。
在LRU算法中,最近最少使用的页面被先换出。当页6要调入时,内存的状态为5、2、1,考查页6之前调入的页面,分别为5、1、2,可见2为最近一段时间内使用最少的,本次应换出,然后把页6调入内存。
发生缺页中断的次数为11。
在OPT算法中,在最远的将来才被访问的页面被先换出。当页6要调入时,内存的状态为1、2、5,考查页6后面要调入的页面,分别为2、1、2、…,可见5为最近一段时间内使用最少的,本次应换出,然后把页6调入内存。
OPT算法因为要知道后面请求的页框,因此我觉得这个算法有个小小的bug,如果在某个请求中,若在该请求的页框之后的页框序列中至少存在一个和当前内存块中不匹配的页框,则按照内存块的顺序(从上往下)替换没有出现的页框。比如上面那个OPT例子。对于最后一个页框请求,因为6未命中,且6之后没有请求的序列,因此应该替换3,所以替换后的序列为6
,
2
,1
。
4.
.假设一个磁盘有200个磁道,编号从O~199。当前磁头正在143道上服务,并且刚刚完成了125道的请求。如果寻道请求队列的顺序是:
86,147,9l,177,94,150,102,175,130
问:为完成上述请求,使用最短寻道时间优先磁盘调度算法SSTF时,磁头移动的总量是多少?(要求写出分析过程)
(147-143)+(150-147)+(150-130)+(130-102)+(102-94)+(94-91)+(91-86)=162
5.
银行家算法(操作系统)
在银行家算法中,某T0时刻的资源分配情况如下:(有三类资源A、B、C,五
个进程P0、P1、P2、P3、P4)
Max
Allocation
Need
Available
A
B
C
A
B
C
A
B
C
A
B
C
P0
7
5
3
0
1
0
7
4
3
3
3
2
P1
3
2
2
2
0
0
1
2
2
P2
9
0
2
3
0
2
6
0
0
P3
2
2
2
2
1
1
0
1
1
P4
4
3
3
0
0
2
4
3
1
试问:
1.该状态是否安全?
2.在T0时刻,P1发出请求Request(1,1,2),系统能否满足?为什么?
答案:
1、这是安全状态:
P1的需求小于可用资源数,先满足P1的请求,然后回收P1资源:可用资源变为
(3,3,2)+(2,0,0)=(5,3,2);
这时P3可分配,P3结束后回收资源,可用资源为(5,3,2)+(2,1,1)=(7,4,3)
这时P0可分配,P0结束后回收资源,可用资源为(7,4,3)+(0,1,0)+(7,5,3)
接下来是P2,结束后可用资源为(7,5,3)+(3,0,2)=(10,5,5)
最后分配P4,结束后可用资源为(10,5,5)+(0,0,2)=(10,5,7)
这样得到一个安全序列:P1-P3-P0-P2-P4,所以T0状态是安全的。
2、T0时刻P1请求(1,1,2)<可用资源数(3,3,2),可以直接满足。
篇3:计算机操作系统实验报告
计算机操作系统实验报告 本文关键词:操作系统,实验,计算机,报告
计算机操作系统实验报告 本文简介:计算机操作系统实验报告实验一一、实验目的在单处理器环境下,实现互斥和同步的控制。熟悉并掌握常用Windows命令行。更进一步理解PV操作的并发控制的实现。二、Windows命令行常用命令dir是英文单词directory(目录)的缩写,主要用来显示一个目录下的文件和子目录。md是英文makedire
计算机操作系统实验报告 本文内容:
计算机操作系统实验报告
实验一
一、实验目的
在单处理器环境下,实现互斥和同步的控制。
熟悉并掌握常用Windows命令行。
更进一步理解PV操作的并发控制的实现。
二、Windows命令行常用命令
dir是英文单词directory(目录)的缩写,主要用来显示一个目录下的文件和子目录。
md是英文make
directory(创建目录)的缩写。功能:创建一个子目录
cd是英文change
directory(改变目录)的缩写,功能:改变目录
rd是英文remove
directory(删除目录)的缩写,功能;:删除目录
copy功能:复制一个或一组文件至指定的目录中
del是英文delete(删除)的缩写,功能:删除指定目录下一个或一组文档
edit功能:edit是一个简单的编辑软件,可用于编辑程序或批处理文件。
bacc功能:编译指定的文件(如bacc
dd)
bainterp功能:运行指定文件(如:bainterp
dd)
三、并发程序设计
题目:在BACI环境下,对程序并发执行的实验:
(1)没有控制时正确的程序执行的结果不正确;
(2)BACI中PV操作的并发控制的实现。
实验1、多进程共享内存堆栈
(1)设计思路:
(2)代码:
int
stack[10];
semaphore
s=1;
int
top=4;
void
release(int
free)
{
p(s);
top++;
coutbuf;
if(buf%2)
v(s2);
else
v(s3);}
void
w1()
{
p(s2);
cout0配合使用,返回队列中第一个类型不为msgtyp的消息
?IPC_NOERROR
如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。
msgrcv手册中详细给出了消息类型取不同值时(>0;
<0;
=0),调用将返回消息队列中的哪个消息。
msgrcv()解除阻塞的条件有三个:
1.消息队列中有了满足条件的消息;
2.
msqid代表的消息队列被删除;
3.调用msgrcv()的进程被信号中断;
调用返回:成功返回读出消息的实际字节数,否则返回-1。
3)int
msgsnd(int
msgqid,struct
msgbufmsgp,size_t
msgsz,int
msgflg)
向msgid代表的消息队列发送一个消息,即将发送的消息存储在msgp指向的msgbuf结构中,消息的大小由msgze指定。
对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。造成msgsnd()等待的条件有两种:
?当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;
?当前消息队列的消息数(单位“个“)不小于消息队列的总容量(单位“字节数“),此时,虽然消息队列中的消息数目很多,但基本上都只有一个字节。
调用返回:成功返回0,否则返回-1。
4)int
msgctl(int
msgqid,int
cmd,struct
msgqid_dsbuf)
该系统调用对由msqid标识的消息队列执行cmd操作,共有三种cmd操作:IPC_STAT、IPC_SET
、IPC_RMID。
1.
IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msqid结构中;
2.
IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msqid结构中;可设置属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同时,也影响msg_ctime成员。
3.
IPC_RMID:删除msqid标识的消息队列;
调用返回:成功返回0,否则返回-1。
四、消息队列应用实例
(1)题目:基于通信的字符串传递,实现在客户端输入一个字符串,服务器端进行倒序,再到客户端输出。
client.c
#include
#include
#include
#define
MSGKEY
75
struct
msgform
{
long
mtype;
char
sour[256];
char
dest[256];
int
sour_pid;
char
mtext[256];
};
int
length
=
sizeof(struct
msgform)-sizeof(long);
main()
{
struct
msgform
msg;
int
msgqid,pid;
msgqid
=
msgget(MSGKEY,0777);
printf(“msgqid=%d/n“,msgqid);
pid=getpid();
printf(“input
string
:“);
scanf(“%s“,msg.sour_pid
=
pid;
msg.mtype=1;
msgsnd(msgqid,msgrcv(msgqid,printf(“client:
msgqid
=
%d/n“,msgqid);
printf(“receive
from
pid
=
%d/n“,msg.sour_pid);
printf(“receive
string
is
%s/n“,msg.dest);
}
server.c
#include
#include
#include
#define
MSGKEY
75
struct
msgform
{
long
mtype;
char
sour[256];
char
dest[256];
int
sour_pid;
char
mtext[256];
}msg;
int
msgqid;
int
length
=
sizeof(struct
msgform)-sizeof(long);
main()
{
int
i,pid;
extern
cleanup();
for(i=0;i=0;i--)
msg.dest[j++]
=
msg.sour[i];
printf(“string
is
%s/n“,msg.dest);
msgsnd(msgqid,}
}
cleanup(){
msgctl(msgqid,IPC_RMID,0);
exit(0);
}
(2)两个进程利用通信进行协作,实现简单的四则运算。一个进程称为客户进程(Client),其任务是从键盘上接收3个参数:两个操作数和一个运算操作符,然后把这3个参数发送给另一个进程,即服务器进程(Server);服务器进程接收客户进程的请求,并根据提供的运算操作符,对两个操作数进行运算,服务器把运算的结果返回给客户。
client:
#include
#include
#include
#define
MSGKEY
75
struct
msgform
{
long
mtype;
float
a,b,result;
char
f[3];
int
sour_pid;
};
int
length
=
sizeof(struct
msgform)-sizeof(long);
main()
{
struct
msgform
msg;
int
msgqid,pid;
msgqid
=
msgget(MSGKEY,0777);
pid=getpid();
printf(“input
a
=
“);
scanf(“%f“,printf(“input
b
=
“);
scanf(“%f“,printf(“input
operator
=
“);
scanf(“%s“,if(msg.f[0]==
/
return
0;}
msg.sour_pid
=
pid;
msg.mtype=1;
msgsnd(msgqid,msgrcv(msgqid,printf(“result
=
%f/n“,msg.result);}
server:
#include
#include
#include
#define
MSGKEY
75
struct
msgform{
long
mtype;
float
a,b,result;
char
f[3];
int
sour_pid;};
int
msgqid;
int
length
=
sizeof(struct
msgform)-sizeof(long);
main()
{
struct
msgform
msg;
int
i,pid;
extern
cleanup();
for(i=0;i<20;i++)
signal(i,cleanup);
msgqid
=
msgget(MSGKEY,0777|IPC_CREAT);
printf(“server
is
waiting./n“);
for(;;)
{
msgrcv(msgqid,printf(“a
=
%f/n“,msg.a);
printf(“b
=
%f/n“,msg.b);
printf(“f
=
%s/n“,msg.f);
if(msg.f[0]==
+
)
msg.result
=msg.
a+msg.b;
else
if(msg.f[0]==
-
)
msg.result
=
msg.a-msg.b;
else
if(msg.f[0]==
)
msg.result
=
msg.a*msg.b;
else
if(msg.f[0]==
/
)
msg.result
=
msg.a/msg.b;
msg.mtype
=
msg.sour_pid;
msg.sour_pid
=
getpid();
printf(“%f
%s
%f
=
%f/n“,msg.a,msg.f,msg.b,msg.result);
msgsnd(msgqid,}}
cleanup(){
msgctl(msgqid,IPC_RMID,0);
exit(0);}
实验心得:每一次课程设计度让我学到了在平时课堂不可能学到的东西。所以我对每一次课程设计的机会都非常珍惜。不一定我的课程设计能够完成得有多么完美,但是我总是很投入的去研究去学习。总结一下有以下体会。
1、同学间的讨论,这是很重要的。老师毕竟比较忙。对于课程设计最大的讨论伴侣应该是同学了。能和学长学姐讨论当然再好不过了,没有这个机会的话,和自己班上同学讨论也是能够受益匪浅的。大家都在研究同样的问题,讨论起来,更能够把思路理清楚,相互帮助,可以大大提高效率。
2、敢于攻坚,越是难的问题,越是要有挑战的心理。这样就能够达到废寝忘食的境界。当然这也是不提倡熬夜的,毕竟有了精力才能够打持久战。但是做课设一定要有状态,能够在吃饭,睡觉,上厕所都想着要解决的问题,这样你不成功都难。
3、最好在做课设的过程中能够有记录的习惯,这样在写实验报告时能够比较完整的回忆起中间遇到的各种问题。比如当时我遇到我以前从未遇到的段错误的问题,让我都不知道从何下手。在经过大量的资料查阅之后,我对段错误有了一定的了解,并且能够用相应的办法来解决。
13