河南自考操作系统实验报告电子稿

河南省高等教育自学考试 实 验 报 告 册

计算机及应用专业(本科段)

《操作系统》

姓名 准考证号 所属地市 实验地点 实验日期 实验总成绩指导教师签名实验单位(实验室)意见: 主考院校审核意见:

河南科技大学自学考试办公室

2014 年 9 月 14 日

1

目 录

一、 实验报告要求…………………………………………………..1

二、 实验一:单处理器系统的进程调度模拟……………………..2

三、 实验二:可变分区管理方式的主存分配回收模拟…………...5

四、 实验三:文件操作模拟………………………………………...8

五、 实验四:银行家算法的模拟……………………………………10

2

实验报告要求

1、 实验报告应包括以下的内容:

(1)程序清单

(2)实验结果

(3)分析与讨论

2、实验报告应写明实验名称、班号、实验者姓名、学号、将实验报告整理装订好,按指导教师规定的时间上交。

基本实验方法

本实践环节要求学生能够顺利完成《数据库原理》、《数据结构》、《操作系统》、《面向对象程序设计》几门课程的实践操作 实验所用器件、设备的简单介绍

所有实验在586以上的微机上进行,运行环境为VFP、C语言、C++语言和Windows、Linux操作系统。

3

实验一:单处理器系统的进程调度模拟

一、 实验学时:2学时

二、 实验目的:通过模拟单处理器系统的进度调度,了解进程的构成、进程的组织及进程的状态及其转换,掌握进程调度策略。

三、 实验设备:本实验在586以上的微机上进行,运行环境为TurboC语言。

四、 样例:(参看《实践性环节培训与考核基本要求》P45)

五、 实验内容:

数据结构及说明:(模拟实验采用时间片轮调度)

Pcb-list是用于存放进程控制块的一个结构数组,每个元素都是一个Pcb结构。

Clock是自定义时钟 TIMESLTICE是时间片大小

NUMBER是系统允许并发执行的最大进程数

List/tail是进程就绪队列的头/尾指针

算法:

定义变量; 初始化就绪队列;

初始化PCB—LIST

CPU查询有多少进程输入,查到值赋给N;

对每个进程 输入到达进程的名称和运行时间

调用函数Pcb—malloc()给进程分配pcb块;

将进程加入就绪队列;

系统调度;(用schedule()实现)

4

if(运行完毕)

输出结束条件:

用用户控制结束。

(一)、实验目的

通过模拟单处理器系统的进度调度,了解进程的构成、进程的组织及进程的状态及其转换,掌握进程调度策略。

(二)、程序清单

#include "stdio.h"

#define running 1 /*用running 表示进程处于运行态*/

#define aready 2 /*用aready表示进程处于就绪态*/

#define blocking 3 /*用blocking表示进程处于等待态*/

#define sometime 5 /*用sometime 表示时间片大小*/

#define n 10 /* 假定系统允许进程个数为10 */

struct

{

int name; /*进程标识符*/

int status; /*进程状态*/

int ax, bx, cx,dx; /*进程现场信息,通用寄存器内容*/

int pc; /*进程现场信息,程序计数器内容*/

int psw; /*进程现场信息,程序状态字寄存器内容*/

int next; /*下一个进程控制块的位置*/

}pcbarea[n]; /*定义模拟进程控制块区域的数组*/

int PSW,AX,BX,CX,DX,PC,TIME; /*模拟寄存器*/

int run; /*定义指向正在运行进程的进程控制块的指针*/

struct

{

int head;

int tail;

}ready; /*定义指向就绪队列的头指针head和尾指针tail*/

int block; /*定义指向等待队列的指针*/

int pfree; /*定义指向空闲进程控制块队列的指针*/

sheduling( )

/*进程调度函数*/

{

int i;

if (ready.head==-1) /*空闲进程控制块队列为空,退出*/

{

5

printf("无就绪进程\n");

return 0;

}

i=ready.head; /*就绪队列头指针赋给i*/

ready.head=pcbarea[ready.head].next;/*就绪队列头指针后移*/

if(ready.head==-1)ready.tail=-1;/*就绪队列为空,修正尾指针ready.tail*/ pcbarea[i].status=running;/*修改进程控制块状态*/

TIME=sometime; /*设置相对时钟寄存器*/

/*恢复该进程现场信息:*/

AX=pcbarea[run].ax;

BX=pcbarea[run].bx;

CX=pcbarea[run].cx;

DX=pcbarea[run].dx;

PC=pcbarea[run].pc;

PSW=pcbarea[run].psw;

/*修改指向运行进程的指针*/

run=i;

return 0;

}/*进程调度函数结束*/

create( int x)

/*创建进程*/

{

int i;

if(pfree==-1) /*空闲进程控制块队列为空*/

{

printf("无空闲进程控制块,进程创建失败\n");

return 0;

}

i=pfree;/*取空闲进程控制块队列的第一个*/

pfree=pcbarea[pfree].next;/*pfree后移*/

/*填写该进程控制块内容:*/

pcbarea[i].name=x;

pcbarea[i].status=aready;

pcbarea[i].ax=x;

pcbarea[i].bx=x;

pcbarea[i].cx=x;

pcbarea[i].dx=x;

pcbarea[i].pc=x;

pcbarea[i].psw=x;

if(ready.head!=-1)

{

/*就绪队列不空时,挂入就绪队列方式*/

pcbarea[ready.tail].next=i;

ready.tail=i;

6

pcbarea[ready.tail].next=-1;

}

else

{

/*就绪队列空时,挂入就绪队列方式:*/

ready.head=i;

ready.tail=i;

pcbarea[ready.tail].next=-1;

}

} /*进程创建函数结束*/

main( )

{

/*系统初始化*/

int num,j;

run=ready.head=ready.tail=block=-1;

pfree=0;

for(j=0;j<n-1;j++)

pcbarea[j].next=j+1;

pcbarea[n-1].next=-1;

printf("输入进程编号(避免编号的冲突,以负数输入结束,最多可以创建10个进程):\n");

scanf("%d",&num);

while(num>0)

{

create(num);

scanf("%d",&num);

}

sheduling( );

if(run!=-1)

{

printf("进程名 进程状态 寄存器内容:ax bx cx dx pc psw:\n");

printf("%4d%10d %14d%3d%3d%3d%3d%3d\n",pcbarea[run].name,

pcbarea[run].status,pcbarea[run].ax, pcbarea[run].bx, pcbarea[run].cx, pcbarea[run].dx, pcbarea[run].pc, pcbarea[run].psw);

}

return 0;

}/*main( )结束*/

(三)、实验中出现的问题及解决的方法

这个实验模拟单处理器系统的进度调度,了解进程的构成、进程的组

织及进程的状态及其转换,掌握进程调度策略。

7

8

实验二:可变分区管理方式的主存分配回收模拟

一、 实验学时:2学时

二、 实验目的:通过模拟可变分区管理方式下主存的分配和回收,主要了解内存的管理思想,以及掌握分区的几种策略。

三、 实验设备:本实验在586以上的微机上进行,运行环境为TurboC语言。

四、 样例:(参看《实践性环节培训与考核基本要求》P54)

五、 实验内容:

数据结构及说明:(模拟试验采用首次适应策略)

空闲区链表FBC,分配区链表ABC;

表中纪录块的起始地址和大小,块按照地址大小从小到大排列。 功能实现

分配时:根据作业的大小,从第一个空闲块查找,将找到的第一个足够大的空闲块分配给该作业,返回给用户该块始地址。

回收时:根据用户提供的作业的始地址,在分配区表中查找,若找到,加入空闲区链表,提示用户释放成功。

显示:用户可随时选择查看内存分配状态图。

主要子函数

Void show-block void display-men(void) void display(void) void add-abcNode void assign() void add-fbcNode

9

void release(void)

(一)、实验目的

通过模拟可变分区管理方式下主存的分配和回收,主要了解内存的管理思想,以及掌握分区的几种策略。

(二)、程序清单

//动态分区存储管理方式的主存分配回收

#include<fstream.h>

#include<iostream.h>

#include<iomanip.h>

#include<string.h>

#include<process.h>

#define n 10 //假定系统允许的最大作业为,假定模拟实验中n值为10

#define m 10 //假定系统允许的空闲区表最大为m,假定模拟实验中m值为10 #define minisize 100

ofstream out("output.txt");

typedef struct

{

float address; //已分分区起始地址

float length; //已分分区长度,单位为字节

int flag; //已分配区表登记栏标志,用"0"表示空栏目,实验中只支持一个字符的作业名 }used; //已分配区表

used used_table[n];

typedef struct

{

float address; //空闲区起始地址

float length; //空闲区长度,单位为字节

int flag; //空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配

}freed; //空闲区表

freed free_table[m];

//采用最优分配算法分配xk大小的空间

void allocate(char J,float xk)

{

int i,k;

float ad;

k=-1;

for(i=0;i<m;i++) //寻找空间大于xk的最小空闲区登记项k

if(free_table[i].length>=xk&&free_table[i].flag==1)

if(k==-1||free_table[i].length<free_table[k].length)

k=i;

if(k==-1)//未找到可用空闲区,返回

{

10

cout<<"无可用空闲区"<<endl;

return;

}

//找到可用空闲区,开始分配:若空闲区大小与要求分配的空间差小于msize大小,则空闲区全部分配;若空闲区大小与要求分配的空间差大于minisize大小,则从空闲区划出一部分分配

if(free_table[k].length-xk<=minisize)

{

free_table[k].flag=0;

ad=free_table[k].address;

xk=free_table[k].length;

}

else

{

free_table[k].length=free_table[k].length-xk;

ad=free_table[k].address+free_table[k].length;

}

//修改已分配区表

i=0;

//寻找空表目

while(used_table[i].flag!=0&&i<n) i++;

//无表目填写已分分区

if(i>=n)

{

cout<<"已分配区表长度不足,分配失败,出错"<<endl;

//修正空闲区表

if(free_table[k].flag==0)

free_table[k].flag=1;

//前面找到的是某个空闲分区的一部分

else

{

free_table[k].length=free_table[k].length+xk;

return;

}

}

//修改已分配表

else

{

used_table[i].address=ad;

used_table[i].length=xk;

used_table[i].flag=J;

}

return;

}

11

//回收作业名为J的作业所占主存空间

void reclaim(char J)

{

int i,k,j,s,t;

float S,L;

//寻找已分配表中对应登记项

s=0;

while((used_table[s].flag!=J||used_table[s].flag==0)&&s<n)

s++;

//在已分配表中找不到名字为J的作业

if(s>=n)

{

cout<<"未找到作业,回收失败"<<endl;

return;

}

//修改已分配表

used_table[s].flag=0;

//取得归还分区的起始地址S和长度L

S=used_table[s].address;

L=used_table[s].length;

j=-1;

k=-1;

//寻找回收分区的空闲上下邻,上邻表目k,下邻表目j

i=0;

while(i<m&&(j==-1||k==-1))

{

if(free_table[i].flag==1)

{

if(free_table[i].address+free_table[i].length==S) k=i;//找到上邻 if(free_table[i].address==S+L) j=i;//找到下邻

}

i++;

}

if(k!=-1)

if(j!=-1) //上邻空闲区,下邻空闲区,三项合并

{

free_table[k].length=free_table[j].length+free_table[k].length+L; free_table[j].flag=0;

}

else //上邻空闲区,下邻非空闲区,与上邻合并

free_table[k].length=free_table[k].length+L;

else

if(j!=-1) //上邻非空闲区,下邻为空闲区,与下邻合并

{

12

free_table[j].address=S;

free_table[j].length=free_table[j].length+L; }

else //上下邻均为非空闲区,回收区域直接填入 { //在空闲区表中寻找空栏目

t=0;

while(free_table[t].flag==1&&t<m)

t++;

if(t>=m)//空闲区表满,回收空间失败,将已分配表复原 {

cout<<"主存空闲表没有空间,回收空间失败"<<endl; used_table[s].flag=J;

return;

}

free_table[t].address=S;

free_table[t].length=L;

free_table[t].flag=1;

}

return;

}

//主函数

void main( )

{

int i,j;

float xk;

char s;

ifstream in("input.txt");

//空闲分区表初始化

free_table[0].address=10240;

free_table[0].length=102400;

free_table[0].flag=1;

for(i=1;i<m;i++)

free_table[i].flag=0;

//已分配表初始化

for(i=0;i<n;i++)

used_table[i].flag=0;

while(1)

{

cout<<" 请输入演示功能项: "<<endl;

cout<<"================================="<<endl<<endl; cout<<" 0.退出 "<<endl<<endl; cout<<" 1.分配主存 "<<endl<<endl; cout<<" 2.回收主存 "<<endl<<endl; 13

cout<<" 3.显示主存 "<<endl<<endl;

cout<<"================================="<<endl<<endl;

cout<<" 请输入(0-3):"<<endl;

cin>>j;

cout<<j<<endl;

cout<<endl;

switch(j)

{

case 0:

exit(0);

case 1:

cout<<"输入作业名s(注意:只能是一个字符): "<<endl;

cin>>s;

cout<<s<<endl;

cout<<"作业所需长度xk: "<<endl;

cin>>xk;

cout<<xk<<endl;

allocate(s,xk);

break;

case 2:

cout<<"输入要回收分区的作业名(注意:只能是一个字符)"<<endl;

cin>>s;

cout<<s<<endl;

reclaim(s);

break;

case 3:

cout<<"输出空闲区表:\n起始地址 分区长度 标志\n";

for(i=0;i<m;i++)

cout<<setw(6)<<free_table[i].address<<setw(9)<<free_table[i].length<<setw(6)<<free_table[i].flag<<endl;

cout<<" 输出已分配区表:\n起始地址 分区长度 标志\n";

for(i=0;i<n;i++)

if(used_table[i].flag!=0)

cout<<setw(6)<<used_table[i].address<<setw(9)<<used_table[i].length<<setw(6)<<char(used_table[i].flag)<<endl;

else

cout<<setw(6)<<used_table[i].address<<setw(9)<<used_table[i].length<<setw(6)<<used_table[i].flag<<endl;

break;

default:

cout<<"没有该选项"<<endl;

14

}//case

}//while

}//主函数结束

(三)、实验中出现的问题及解决的方法

这个实验通过模拟可变分区管理方式下主存的分配和回收,了解内存的管理思想,并且掌握分区的几种策略。

15

实验三:文件操作模拟

一、 实验学时:2学时

二、 实验目的:通过编程练习文件系统提供的文件操作,了解和掌握文件管理系统工作原理。主要了解文件的物理结构、目录管理、外存空间的管理以及文件的保护和保密。

三、 实验设备:本实验在586以上的微机上进行,运行环境为TurboC语言。

四、 样例:(参看《实践性环节培训与考核基本要求》P96)

五、 实验内容:

实现文件的建立和读写操作。首先建立文件File1和File2,然后从键盘输入,并将输入的内容写入File1中,然后将File1中的内容以倒序写入File2中,最后将File2的内容显示。

(一)、实验目的

过编程练习文件系统提供的文件操作,了解和掌握文件管理系统工作原理。主要了解文件的物理结构、目录管理、外存空间的管理以及文件的保护和保密。

(二)、程序清单

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.ArrayList;

16

public class Test

{

public static void main(String[] args) throws IOException { } File file1 = new File("D:/f1.txt"); File file2 = new File("D:/f2.txt"); int c; InputStream input1 = System.in; InputStreamReader reader1 = new InputStreamReader(input1); FileWriter writer1 = new FileWriter(file1); while ((c = reader1.read()) != -1) { } writer1.close(); FileReader reader2 = new FileReader(file1); FileWriter writer2 = new FileWriter(file2); ArrayList<Integer> list = new ArrayList<Integer>(); while ((c = reader2.read()) != -1) { } for (int i = list.size() - 1; i >= 0; --i) { } writer2.close(); writer2.write(list.get(i)); list.add(c); writer1.write(c);

(三)、实验中出现的问题及解决的方法

通过这个实验让我更加了解了操作系统中的原理和使用方式。

17

实验四 银行家算法的模拟

一、实验学时:2学时

二、实验目的:通过对银行家算法的模拟,了解死锁的概念、死锁的本质以及掌握解决死锁的方法。

三、 实验设备:本实验在586以上的微机上进行,运行环境为TurboC语言。

四、 样例:(参看《实践性环节培训与考核基本要求》P101)

五、 实验内容:

数据结构定义:

可用资源向量 available

分配矩阵 allocation

剩余需求矩阵 need

系统拥有资源向量 max-resource

安全状态标志向量 finish

程序要求

对每一种资源进行安全检验,要求该程序在静态的条件下输入系统的状态,和每个进程拥有资源的状态,来判断系统是否安全。

(一)、实验目的

通过对银行家算法的模拟,了解死锁的概念、死锁的本质以及掌握解决死锁的方法。

(二)、程序清单

#include <iostream.h>

18

//全局变量定义

int Available[100]; //可利用资源数组

int Max[50][100]; //最大需求矩阵

int Allocation[50][100]; //分配矩阵

int Need[50][100]; //需求矩阵

int Request[50][100]; //M个进程还需要N类资源的资源量 int Finish[50];

int p[50];

int m,n; //M个进程,N类资源

//安全性算法

int Safe()

{

int i,j,l=0;

int Work[100]; //可利用资源数组

for (i=0;i<n;i++)

Work[i]=Available[i];

for (i=0;i<m;i++)

Finish[i]=0;

for (i=0;i<m;i++)

{

if (Finish[i]==1)

continue;

else

{

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

{

if (Need[i][j]>Work[j])

break;

}

if (j==n)

{

Finish[i]=1;

for(int k=0;k<n;k++)

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

p[l++]=i;

i=-1;

}

else continue;

}

if (l==m)

{

cout<<"系统是安全的"<<'\n';

cout<<"系统安全序列是:\n";

19

for (i=0;i<l;i++)

{

cout<<p[i];

if (i!=l-1)

cout<<"-->";

}

cout<<'\n';

return 1;

}

}

}

//银行家算法

int main()

{

int i,j,mi;

cout<<"输入进程的数目:\n";

cin>>m;

cout<<"输入资源的种类:\n";

cin>>n;

cout<<"输入每个进程最多所需的各类资源数,按照"<<m<<"x"<<n<<"矩阵输入\n"; for (i=0;i<m;i++)

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

cin>>Max[i][j];

cout<<"输入每个进程已经分配的各类资源数,按照"<<m<<"x"<<n<<"矩阵输入\n"; for (i=0;i<m;i++)

{

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

{

cin>>Allocation[i][j];

Need[i][j]=Max[i][j]-Allocation[i][j];

if (Need[i][j]<0)

{

cout<<"你输入的第"<<i+1<<"个进程所拥有的第"<<j+1<<"个资源错误,请重新输入:\n";

j--;

continue;

}

}

}

cout<<"请输入各个资源现有的数目:\n";

for (i=0;i<n;i++)

cin>>Available[i];

Safe();

20

while (1)

{

cout<<"输入要申请的资源的进程号:(第一个进程号为0,第二个进程号为1,依此类推)\n";

cin>>mi;

cout<<"输入进程所请求的各个资源的数量\n";

for (i=0;i<n;i++)

cin>>Request[mi][i];

for (i=0;i<n;i++)

{

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

{

cout<<"所请求资源数超过进程的需求量!\n";

return 0;

}

if (Request[mi][i]>Available[i])

{

cout<<"所请求资源数超过系统所有的资源数!\n";

return 0;

}

}

for (i=0;i<n;i++)

{

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

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

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

}

if (Safe())

cout<<"同意分配请求~~~\n";

else

{

cout<<"SORRY╮(╯▽╰)╭……你的请求被拒绝…\n";

for (i=0;i<n;i++)

{

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

Allocation[mi][i]-=Request[mi][i];

Need[mi][i]+=Request[mi][i];

}

}

for (i=0;i<m;i++)

Finish[i]=0;

char Flag; //标志位

cout<<"是否再次请求分配?是请按Y/y,否请按N/n";

while (1)

21

}

} { cin>>Flag; if (Flag=='Y'||Flag=='y'||Flag=='N'||Flag=='n') break; else { cout<<"请按要求重新输入:\n"; continue; } } if (Flag=='Y'||Flag=='y') continue; else break;

(三)、实验中出现的问题及解决的方法

没有什么问题但是银行家算法,有效的防止和避免死锁的发生,值得好好学习。

22

相关推荐