人人范文网 其他范文

操作系统课程设计(精选多篇)

发布时间:2022-05-26 18:05:55 来源:其他范文 收藏本文 下载本文 手机版

推荐第1篇:操作系统课程设计

长春理工大学 软件学院 0813111班 27号

姓名:丁为胜 一. 概述

1、课程设计目的及任务课程设计地点及要求

每个学生一台微机,需要安装windows98或windows2000操作系统,配备VC、VB、java或C编程语言,每个学生上机时间不少于24个小时。

操作系统是计算机专业的核心专业课,“操作系统课程设计”是理解和巩固操作系统基本理论、原理和方法的重要的实践环节。

操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握操作系统基本理论与管理方式。在算法基础上,解决实际的管理功能的问题,提高学生实际应用、编程的能力。

主要任务是实现操作系统和相关系统软件的设计,其中涉及进程创建,同步,进程间的通信,存储管理,文件系统等操作系统概念。

2.课程设计地点及要求

每个学生一台微机,需要安装windows98或windows2000操作系统,配备VC、VB、java或C编程语言,每个学生上机时间不少于24个小时。

3.课程设计的内容

设计二: 设计任务:

掌握进程的管道通讯机制和信号量同步互斥机制。 1. 进程的管道通讯

编制一个程序,程序中创建一个子进程。然后父子进程各自独立运行,父进程不断地在标准输入设备上读入小写字母,写入管道。子进程不断地从管道中读取字符,转换为大写字母后输出到标准输出设备上。当读到x时,结束。

2. 信号量实现的同步互斥机制

编制一个程序,程序中创建5个子进程,代表五位哲学家,然后父进程结束。使用信号量机制解决哲学家进餐问题。当哲学家进餐时,屏幕输出:

[进程号] eating! 当哲学家思考时,屏幕输出: [进程号] thinging! 相关的系统调用和函数:pipe(); write(); read(); semget(); sepop(); semctl(); 要求:查找并阅读上述系统调用的相关资料,将上述相关的函数封装为P( )、V( )操作,使用你封装的P( )、V( )操作实现5位哲学家的同步和互斥。

二. 设计的基本概念和原理

1.进程的管道通讯

管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。命名管道(Named Pipes)是在管道服务器和一台或多台管道客户机之间进行单向或双向通信的一种命名的管道。一个命名管道的所有实例共享同一个管道名,但是每一个实例均拥有独立的缓存与句柄,并且为客户——服务通信提供有一个分离的管道。实例的使用保证了多个管道客户能够在同一时间使用同一个命名管道。

2.信号量实现的同步互斥机制

规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号 的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即 五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获 得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲 学家会较先可以吃饭,因此不会出现饿死的哲学家。

三. 总体设计

1.实现的方法和主要技术路线

1.无名管道

无名管道用于具有亲缘关系的父子进程,子子进程之间的通讯。它的实现函数有 int pipe(int fd[2]);

//fd[2] 为描述符数组,包含一个读描述符与一个写描述符,在使用管道通信时,关闭某些不需要的读或写描述符,建立起单向的读或写管道,然后用read 和write 像操作文件一样去操作它即可。

如图便是进程1 到进程2 的一个读管道。

分别在父进程和父子进程里向管道写数据,然后在子进程和子子进程里读数据。 2.哲学家进餐伪码:

semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) {

while(true) {

think();

if(i%2 == 0) //偶数哲学家,先右后左。

{

wait (chopstick[ i + 1 ] mod 5) ; wait (chopstick[ i]) ; eat();

signal (chopstick[ i + 1 ] mod 5) ; signal (chopstick[ i]) ; }

Else //奇数哲学家,先左后右。

{

wait (chopstick[ i]) ;

wait (chopstick[ i + 1 ] mod 5) ; eat();

signal (chopstick[ i]) ;

signal (chopstick[ i + 1 ] mod 5) ; } } 四. 详细设计

进程的管道通信代码: import java.io.IOException; import java.io.PipedReader;

public cla ReceiverThread1 extends Thread { PipedReader pipedReader;

public ReceiverThread1(SenderThread1 sender) throws IOException

{

pipedReader=new PipedReader(sender.getPipedWriter());

}

public void run()

{ char[] ch=new char[100]; StringBuffer sb=null; String str=null; int i=0; try {

while((i=pipedReader.read(ch))!=-1)

{

sb=new StringBuffer();

for(int j=0;j

{

sb.append(ch[j]);

}

str=sb.toString();

System.out.println(\"子进程读取的字符为:\"+str.toUpperCase());

if(!str.endsWith(\"x\"))

{

System.out.print(\"父进程读入字符为:\");

}else if(str.endsWith(\"x\"))

{

System.out.println(\"结束无法再次输入字符\");

}

} } catch (IOException e) {

e.printStackTrace(); }finally{

try {

pipedReader.close();

} catch (IOException e) {

e.printStackTrace();

} }

}

}

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PipedWriter;

public cla SenderThread1 extends Thread { PipedWriter pipedWriter;

public SenderThread1() {

pipedWriter=new PipedWriter(); }

public PipedWriter getPipedWriter() {

return pipedWriter; }

public void run()

{ BufferedReader ir=new BufferedReader(new InputStreamReader(System.in)); char[] ch=new char[100]; StringBuffer sb=null; String str=null; int i=0; System.out.print(\"父进程读入字符为:\"); try {

while((i=ir.read(ch))!=-1)

{

sb=new StringBuffer();

for(int j=0;j

{

if(ch[j]>=\'a\' && ch[j]

{

sb.append(ch[j]);

if(ch[j]==\'x\')

{

break;

}

}

}

str=sb.toString();

pipedWriter.write(str);

if(str.startsWith(\"x\")||str.endsWith(\"x\"))

{

break;

// this.stop();

}

}

} catch (IOException e) {

e.printStackTrace(); }finally{

try {

ir.close();

pipedWriter.close();

} catch (IOException e) {

e.printStackTrace();

}

}

} }

public cla ThreadComm1 { public static void main(String[] args)throws Exception{ SenderThread1 sender=new SenderThread1(); ReceiverThread1 receiver=new ReceiverThread1(sender); sender.start(); receiver.start(); } } 哲学家进餐问题代码: #include \"stdafx.h\" using namespace std; bool chop[100];//定义筷子 cla ph { protected: bool * left,* right;//哲学家的左右手指向的筷子

int eattime;//哲学家的吃饭时间 public: bool check()//用于检查哲学家左右手的筷子是不是被占用

{

if(*left && *right)

return true;

else

return false; } void eat(int ineattime)//哲学家开始进餐

{

eattime=ineattime;

*left=false;

*right=false; } bool finish()//检查哲学家是否完成进餐

{

if(eattime>0)//没完成的话剩余时间减少

{

eattime--;

if(eattime==0)//完成的话归还筷子

{

*left=true;

*right=true;

return true;

}

else

return false;

}

else

return false; } void init(int num,int max)//初始化哲学家,指定他们使用的筷子

{

eattime=0;

left=&chop[num];

if(num

right=&chop[num+1];

else

right=&chop[0]; } }; void main() { system(\"title 哲学家进餐问题\"); int in,i,temp,time,j=1; queue Q; ph P[100];

for(int i=0;i

chop[i]=1;

} for(int i=0;i>in; if(in==0)

break; else

if(in>5)

{

cout

}

else

{

Q.push(in-1);

} } cout>time; system(\"CLS\"); system(\"color 0a\"); while(!Q.empty()) { temp=Q.front(); Q.pop(); if(P[temp].check()) {

P[temp].eat(time);

cout

if(temp+2>5)

cout

else

cout

Q.push(temp); } for(i=0;i

{

if(P[i].finish())

cout

}

//Q.push(-1);

for(i=0;i

{

temp=Q.front();

Q.pop();

//if(temp!=-1)

{

cout

Q.push(temp);

}

//else

{

// Q.pop();

break;

}

} } for(int j=0;j

if(P[i].finish())

{

cout

} getch(); }

推荐第2篇:操作系统课程设计

湖北民族学院信息工程学院11级计算机专业操作系统课程设计

(操作系统课程设计)

连续动态分区内存

管理模拟实现

学生姓名: 韩 慧 学生学号: 031140312 班 级: 031140--3

031140

1、0

2、0

3、04班制

二〇一三年十二月

1 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

目录

《操作系统》课程设计.......................................................1 引言......................................................................3 课程设计目的和内容 ......................................................3 需求分析.........................................................................3 概要设计...................................................................3 开发环境........................................................................4 系统分析设计.....................................................................4 有关了解内存管理的相关理论..................................................4 内存管理概念........................................................................4 内存管理的必要性..............................................................4 内存的物理组织.............................................................4 什么是虚拟内存.................................................................5 连续动态分区内存管理方式...................................................5 单一连续分配(单个分区)...................................................5

固定分区存储管理...............................................................5 可变分区存储管理(动态分区)..............................................5 可重定位分区存储管理........................................................5 问题描述和分析....................................................................6 程序流程图........................................................................6 数据结构体分析..................................................................8 主要程序代码分析...............................................................9 分析并实现四种内存分配算法 .................................................11 最先适应算.....................................................................11 下次适应分配算法..........................................................13 最优适应算法...............................................................16 最坏适应算法...............................................................18 回收内存算法................................................................20 调试与操作说明.................................................................22

初始界面.......................................................................22 模拟内存分配...............................................................23

已分配分区说明表面............................................................24 空闲区说明表界面.............................................................24 回收内存界面.....................................................................25 重新申请内存界面..........................................................26.总结与体会......................................................................28

2 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

参考文献.........................................................................28

引言

操作系统是最重要的系统软件,同时也是最活跃的学科之一。我们通过操作系统可以理解计算机系统的资源如何组织,操作系统如何有效地管理这些系统资源,用户如何通过操作系统与计算机系统打交道。

存储器是计算机系统的重要组成部分,近年来,存储器容量虽然一直在不断扩大,但仍不能满足现代软件发展的需要,因此,存储器仍然是一种宝贵而又紧俏的资源。如何对它加以有效的管理,不仅直接影响到存储器的利用率,而且还对系统性能有重大影响。而动态分区分配属于连续分配的一种方式,它至今仍在内存分配方式中占有一席之地。

课程设计目的和内容:

理解内存管理的相关理论,掌握连续动态分区内存管理的理论;通过对实际问题的编程实现,获得实际应用和编程能力。

编写程序实现连续动态分区内存管理方式,该程序管理一块虚拟内存,实现内存分配和回收功能。 分析并实现四种内存分配算法,即最先适应算法,下次最先适应算法,最优适应算法,最坏适应算法。内存分配算法和回收算法的实现。

需求分析

动态分区分配是根据进程的实际需要,动态地为之分配内存空间。在实现动态分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配和回收操作这样三个问题。常用的数据结构有动态分区表和动态分区链。在对数据结构有一定掌握程度的情况下设计合理的数据结构来描述存储空间,实现分区存储管理的内存分配功能,应该选择最合适的适应算法(首次适应算法,最佳适应算法,最后适应算法,最坏适应算法),在动态分区存储管理方式中主要实现内存分配和内存回收算法,在这些存储管理中间必然会有碎片的产生,当碎片产生时,进行碎片的拼接等相关的内容

概要设计

本程序采用机构化模块化的设计方法,共分为四大模块。 ⑴最先适应算法实现

从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。 ⑵下次适应分配算法实现

3 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

该算法是最先适应算法的变种。在分配内存空间时,不再每次从表头(链首)开始查找,而是从上次找到空闲区的下一个空闲开始查找,直到找到第一个能满足要求的的空闲区为止,并从中划出一块与请求大小相等的内存空间分配给作业。该算法能使内存中的空闲区分布得较均匀。 ⑶最优适应算法实现

它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。 ⑷最坏算法实现

最坏适应分配算法要扫描整个空闲分区或链表,总是挑选一个最大的空闲分区分割给作业使用。该算法要求将所有的空闲分区按其容量从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。

开发环境:

win7 下 VC++6.0 系统分析设计:

相关算法原理,算法流程图,涉及的数据结构内容都相应包含在各章节中

有关了解内存管理的相关理论

内存管理概念:

内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存不是预先划分好的,而是在系统运行的过程中建立分区.当作业装入主存时,根据作业所需要的主存容量查看是否有足够的主存空间,若有则按需要分割一个分区给该作业;否则令该作业等待.分区长度不固定分区个数不固定。这种存储管理的方法克服了固定分区严重浪费主存的问题,提高了主存资源的利用率。

内存管理的必要性:

内存管理对于编写出高效率的 Windows 程序是非常重要的,这是因为Windows 是多任务系统,它的内存管理和单任务的 DOS 相比有很大的差异。DOS是单任务操作系统,应用程序分配到内存后,如果它不主动释放,系统是不会对它作任何改变的;但 Windows 却不然,它在同一时刻可能有多个应用程序共享内存,有时为了使某个任务更好地执行,Windows 系统可能会对其它任务分配的内存进行移动,甚至删除。因此,我们在 Windows 应用程序中使用内存时,要遵循Windows 内存管理的一些约定,以尽量提高 Windows 内存的利用率。

4 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

1.3 内存的物理组织:

物理地址:

把内存分成若干个大小相等的存储单元,每个存储单元占 8 位,称作字节(byte)。每个单元给一个编号,这个编号称为物理地址(内存地址、绝对地址、实地址)。

二、物理地址空间: 物理地址的集合称为物理地址空间(主存地址空间),它是一个一维空间。

什么是虚拟内存:

虚拟内存是内存管理技术的一个极其实用的创新。它是一段程序(由操作系统调度),持续监控着所有物理内存中的代码段、数据段,并保证他们在运行中的效率以及可靠性,对于每个用户层(user-level)的进程分配一段虚拟内存空间。当进程建立时,不需要在物理内存件之间搬移数据,数据储存于磁盘内的虚拟内存空间,也不需要为该进程去配置主内存空间,只有当该进程被被调用的时候才会被加载到主内存。

连续动态分区内存管理方式的实现

在早期的操作系统中,主存分配广泛采用连续分配方式。 连续分配方式,是指为一个用户程序分配一个连续的内存空间,该连续内存空间指的的是物理内存。下面介绍连续分配的四种方式。

单一连续分配(单个分区)

最简单的存储管理方式,用于多道程序设计技术之前。 内存分为系统区和用户区,系统区由操作系统使用。用户区作为一个连续的分区分配给一个作业。 分区存储管理是满足多道程序设计的最简单的一种存储管理方法,它允许多 4个用户程序同时存在系统内存中,即共享内存空间。 按分区划分方式可分为固定分区和可变分区。

固定分区存储管理

把内存的用户区预先划分成多个分区,每个分区大小可以相同,也可以不同。(分区的划分由计算机的操作员或者由操作系统给出,并给出主存分配表) 分区个数固定,分区的大小固定。 一个分区中可装入一个作业,作业执行过程中不会改变存放区域。 早期的 IBM 的 OS/MFT(具有固定任务数的多道程序系统)采用了这种固定分区的方法。

可变分区存储管理(动态分区)

内存不是预先划分好的,而是在系统运行的过程中建立分区.当作业装入主存时,根据作业所需要的主存容量查看是否有足够的主存空间,若有则按需要分割一个分区给该作业;否则令该作业等待。 分区长度不固定分区个数不固定。 这种存储管理的方法克服了固定分区严重浪费主存的问题,提高了主存资源的利用率。 IBM操作系统OS/MVT采用可变分区存储管理。

5 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

可重定位分区存储管理

解决碎片问题的一种简单方法是采用可重定位分区分配.。 其中心思想是,把不同程序,且在内存中地址不连续的想法让他们连续。

例:内存中现有 3 个空闲区,现有一作业到达,要求获得 30k 内存空间,没有分区满足容量要求,若想把作业装入,可将内存中所有作业进行移动,这样把原来分散的空闲区汇集成一个大的空闲区。 将内存中的作业进行移动使它们连接在一起把原来分散的多个小分区拼接成一个大的空闲区.这个过程称为”紧凑”或”移动”。 需解决的问题:每次”紧凑”后程序或数据装入的物理地址变化采用动态重定位。

问题描述和分析

系统应利用某种分配算法,从空闲分区链表中找到所需大小的分区,如果空闲分区大小大于请求分区大小,则从该分区中按改请求的大小划分出一块内存空间大小划分出一块内存空间分配出去,余下的部分仍留在空闲链表中。然后,将分配区的首址返回给调用者。

当进程运行完毕师范内存时,系统根据回收区的首址,从空闲区中找到相应的插入点,此时可能出现以下四种情况之一:

⑴该空闲区的上下两相邻分区都是空闲区:将三个空闲区合并为一个空闲区。新空闲区的起始地址为上空闲区的起始地址,大小为三个空闲区之和。空闲区合并后,取消可用表或自由链中下空闲区的表目项或链指针,修改上空闲区的对应项。

⑵该空闲区的上相邻区是空闲区:将释放区与上空闲区合并为一个空闲区,其起始地址为上空闲区的起始地址,大小为上空闲区与释放区之和。合并后,修改上空闲区对应的可用表的表目项或自由链指针。

⑶该空闲区的下相邻区是空闲区:将释放区与下空闲区合并,并将释放区的起始地址作为合并区的起始地址。合并区的长度为释放区与下空闲区之和。同理,合并后修改可用表或自由链中相应的表目项或链指针。

⑷两相邻区都不是空闲区:释放区作为一个新空闲可用区插入可用表或自由链。

程序流程图

内存分配流程图,如图

6 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

从头开始查表检索完否?NY返回分区大小>所需大小N继续检索下一个表项Y分区大小-所需大小

内存回收流程图,如图

7 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

开始判断空闲区上下内存情况上为空下为空上下都为空上下都不为空将上面的空闲区合并,并回收将下面的空闲区合并,并回收将上下的空闲区合并,并回收直接将其回收结束 数据结构体分析

⑴进程属性结构体 typedef struct readyque { char name[10]; int size; }readyque,*readyqueue; ⑵空闲链表结构体 typedef struct idlyspace { int from; int size; idlyspace * next; }idlyspace,*idly; ⑶已分配链表结构体 typedef struct busyspace { int from; readyque r;

8 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

busyspace * next; }busyspace,*busy

主要程序代码分析

⑴主函数//代码请添加适当的注释。 int main() { Is=(idly)malloc(sizeof(idlyspace)); Is->from=0; Is->size=256; Is->next=NULL; Is2=Is; Bs=(busy)malloc(sizeof(busyspace)); Bs->next=NULL; int t,t1; printf(\"\\n.......................欢迎来到动态分区存储管理系统..................\\n\\n\"); printf(\"...........................请选择要执行的算法:...........................\\n\"); printf(\".........................1.最先适应算法

...............................\\n\"); printf(\".........................2.下次适应算法 ............................\\n\"); printf(\"..........................3.最优适应算法

...............................\\n\"); printf(\".........................4.最坏适应算法 ................................\\n\"); printf(\"........................................................................\\n\"); printf(\"请输入您的选择:\"); scanf(\"%d\",&t); int i; while(i!=5) {

printf(\"........................................................................\\n\");

printf(\".........................操作菜单如下:(请选择).......................n\");

printf(\"..........................1.输入进程分配空间 ...........................n\");

printf(\".........................2.进程撤销回收空间 ...........................\\n\");

printf(\".........................3.输出所有空闲分区

..........................\\n\");

printf(\"..........................4.输出所有已分配分区..........................\\n\");

printf(\"..........................5.退

出 ..........................\\n\");

printf(\"........................................................................\\n\");

scanf(\"%d\",&i);

switch(i)

{

case 1:

switch(t)

{

case 1:

t1=FF();

9 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

break;

case 2:

t1=NF();

break;

case 3:

t1=BF();

break;

case 4:

t1=WF();

break;

default:

printf(\"选择算法错误\\n\");

return 1;

}

if(t1)

printf(\"分配空间成功\\n\");

else

printf(\"分配空间失败\\n\");

break;

case 2:

t1=recover();

if(t1)

printf(\"回收成功\\n\");

else

printf(\"回收失败\\n\");

break;

case 3:

Isprint();

break;

case 4:

Bsprint();

break;

} } return 0; }

第三章 :分析并实现四种内存分配算法

最先适应算法

空闲区按地址从小到大的次序排列。

分配:当进程申请大小为 SIZE 的内存时,系统顺序查找空闲区表(链),直到找到容量满足要求(≥SIZE)的空闲区为止。从该空闲区中划出大小为 SIZE的分区分配给进程,余下的部分仍作为一个空闲区,但要修改其首址和大小。

10 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

优点:这种算法是尽可能地利用低地址部分的空闲区,而尽量地保证高地址 6部分的大空闲区,有利于大作业的装入。

缺点:主存低地址和高地址分区利用不均衡。在低地址部分集中了许多非常小的空闲区碎片降低了主存的利用率。 最先适应算法 int FF() { int t=0; readyque D; printf“\"请输入进程名:\\”\"); scanf“\"%”\",D.name);

printf“\"输入进程申请空间大小:\\”\"); scanf“\"%”\",&D.size);

idly l=Is; int mt=256; busy b=Bs; idly min=NULL; while(l)

//寻找空闲表中大小满足申请进程所需大小并且起址最小的空闲结点

{

if(D.sizesize)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace));

//如果找到则为进程分配空间

11 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

j->from=min->from;

for(int i=0;i

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size; } return t; }

下次适应分配算法

最先适应算法的变种。

总是从空闲区上次扫描结束处顺序查找空闲区表(链),直到找到第一个满足容量要求的空闲区为止,分割一部分给作业,剩余部分仍作为空闲区。 下次适应分配算法 int NF() { int t=0; readyque D; printf“\"请输入进程名:\\”\"); scanf“\"%”\",D.name);

12 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

printf“\"输入进程申请空间大小:\\”\"); scanf“\"%”\",&D.size);

int mt=256; idly l=Is2; idly min=NULL; busy b=Bs; while(l) //寻找空闲表中大小满足申请进程所需大小并且起址最小的空闲结点

{

if(D.sizesize)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

for(int i=0;i

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

//如果找到则为进程分配空间

13 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

}

//将申请空间进程插入到已分配链表中

j->next=b->next;

b->next=j;

//修改相应空闲节点的起址和大小

min->from=min->from+D.size;

min->size=min->size-D.size;

Is2=min->next;

结点

t=1;

return t; }

l=Is;//l指向空闲表的头

while(l!=Is2)

{

if(D.sizesize)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256) {

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

for(int i=0;i

{

//ls2指向修改结点的下一个

//循环查找

14 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size;

Is2=min->next;

t=1;

return t; } return t; }

最优适应算法

空闲区按容量递增的次序排列。

分配:当进程申请存储空间,系统顺序查找空闲区表(链),直到找到第一个满足容量要求的空闲区为止。 采用最优适应算法选中的空闲区是满足容量要求的最小空闲区。 优点:选中的空闲区是满足容量要求的最小空闲区,而不致于毁掉较大的空闲区。

缺点:空闲区的大小一般与申请分区大小不相等,因此将其一分为二,留下来的空闲区一般情况下是很小的,以致无法使用。随着时间的推移,系统中的小空闲区会越来越多,从而造成存储空间的浪费。 最优适应算法 int BF() { int t=0;

15 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

readyque D; printf“\"请输入进程名:\\”\"); scanf“\"%”\",D.name);

printf“\"输入进程申请空间大小:\\”\"); scanf“\"%”\",&D.size);

idly l=Is; idly min=NULL; int mt=256; busy b=Bs; while(l) //在空闲链中寻找第一个大于所输入的进程大小的空闲块

{

if(D.sizesize)

{

if(l->size

{

mt=l->size; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace)); 空间

j->from=min->from;

//申请分配用于存放进程的内存

//找到第一个满足要求的空闲块

//将第一个满足要求的空闲块(min)的首地址赋给j

for(int i=0;i

{

j->r.name[i]=D.name[i]; 16 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

}

j->r.size=D.size;

while(b->next)

//按从小到大的顺序查找新进程在已分配区中的位置

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size;

} return t; }

最坏适应算法

为了克服最佳适应算法把空闲区切割得太小的缺点,人们提出了一种最坏适应算法,即每次分配时,总是将最大的空闲区切去一部分分配给请求者,剩余的部分仍是一个较大的空闲区。避免了空闲区越分越小的问题。 要求空闲区按容量递减的顺序排列。

分配:进程申请存储区时,检查空闲区表(链)的第一个空闲区的大小是否满足要求,若不满足则令进程等待;若满足则从该空闲区中分配一部分存储区给用户,剩下的部分仍作为空闲区。 最坏适应算法 int WF() { int t=0; readyque D; printf“\"请输入进程名:\\”\"); scanf“\"%”\",D.name);

printf“\"输入进程申请空间大小:\\”\");

//将所输入的进程插入进程链

//改变该空闲块的起始地址 //改变该空闲块的剩余大小 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

scanf“\"%”\",&D.size);

//输入进程申请的空间大小

idly l=Is;//l指向空闲链表ls头

idly min=NULL; int mt=0; busy b=Bs;

//b指向已分配链表Bs头

//找到空闲分区中大小满足进程的请求且尺寸最大的结点

while(l) {

if(D.sizesize) //判断进程所申请的大小是否小于空闲区的各结点大小

{

if(l->size>mt)

{ mt=l->size; min=l;//min指向空闲区中尺寸最大的结点

t=1;

}

}

l=l->next; } if(mt!=0) 点

{

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

for(int i=0;i

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

//判断是否找到了空闲区的满足结

//l指向空闲链表下一个结点

18 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

while(b->next) 置

//寻找插入到已分配链表中的位

{ if(b->next->fromfrom)

b=b->next; else

break;

}

//把此进程结点j插入到已分配链表中

j->next=b->next;

b->next=j;

//修改空闲链表的相应结点的参数

min->from=min->from+D.size;

min->size=min->size-D.size; } return t; }

可变分区的回收

当某个进程释放某存储区时,系统首先检查释放区是否与系统中的空闲区相邻若相邻则把释放区合并到相邻的空闲区去,否则把释放区作为一个空闲区插入到空闲表的适当位置。

释放区与空闲区相邻的四种情况。

(1) 释放区与前空闲区相邻:把释放区与前空闲区合并到一个空闲区。其首址仍为前空闲区首址,大小为释放区大小与空闲区大小之和。

(2) 释放区与后空闲区相邻:则把释放区合并到后空闲区,其首地址为释放区首地址,大小为二者之和。

(3) 释放区与前后两空闲区相邻:这三个区合为一个空闲区,首地址为前空闲区首址,大小为这三个空闲区之和,并取消后空闲区表目。

(4) 释放区不与任何空闲区相邻:将释放区作为一个空闲区,将其大小和首址插入到空闲区表的适当位置。

19 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

回收内存算法

int recover() { readyque D; printf“\"请输入想要回收的进程名\\”\");

scanf“\"%”\",D.name);

busy b=Bs; idly l=Is; while(b->next) 链表中

{

bool yo=1;

for(int i=0;i

{

if(b->next->r.name[i]==D.name[i]) yo=yo*1;

else yo=0;

}

//如果在已分配链表中则释放该结点所占空间

if(yo)

{

int t=b->next->from;

int ts=b->next->r.size;

//查找输入的进程名是否在已分配湖北民族学院信息工程学院11级计算机专业操作系统课程设计

while(l)

{ if(l->from>t+ts) 不邻接

{ idly tl; tl=(idly)malloc(sizeof(idlyspace)); tl->from=t; tl->size=ts; tl->next=l; Is=tl; break; } if(l->from==t+ts)

l->from=t;

l->size=l->size+ts;

busy tb=b->next;

b->next=b->next->next;

free(tb);

return 1; }

if(l->from+l->size

idly tl;

tl=(idly)malloc(sizeof(idlyspace));

tl->from=t;

tl->size=ts;

tl->next=l->next;

l->next=tl;

break; }

else if(l->from+l->size==t)

//所回收进程与空闲结点上邻接 {

//所回收进程与空闲结点上下都不邻接

//所回收进程与空闲结点下邻接 {

//所回收进程与空闲结点上下都 21 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

l->size=l->size+ts;

if(l->from+l->size==l->next->from) 接

{

l->size=l->size+l->next->size;

idly tm=l->next;

l->next=l->next->next;

freI);

}

br

l=l->next;

}

//从已分配链表中释放所回收进程

busy tb=b->next;

b->next=b->next->next;

free(tb);

return 1;

}

b=b->next; } printf(\"没找到这”进程\\n\"); return 0; }

//所回收进程与空闲结点上下都邻调试与操作说明

初始界面

程序初始界面,有四个块选择,选择要执行的算法,调试以最坏算法为例,如图

22 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

选择最坏适应算法,如图

模拟内存分配

给进程a分配内存20,如图

23 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

已分配分区说明表界面

同理,给进程b分配内存30,给进程c分配内存40,给进程d分配50,给进程e分配60,如图

空闲分区说明表界面

24 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

查看空闲分区,如图

回收内存界面

回收进程b和d所占内存,如图

已分配分区说明表和空闲分区说明表 如图

25 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

重新申请内存界面

再为新进程i分配内存30,如图

26 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

根据最坏适应算法结合图所示可知,该算法将会从空闲分区表中选择一块最大的内存空间分配给进程i,从图也可看出该模拟算法实现了最坏适应算法

27 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

总结与体会

本次做的课题是动态分区分配算法实现,此次课程设计成功实现了内存分配和内存回收,内存分配中包含了四种算法,分别是首次适应算法,循环首次适应算法,最佳适应算法和最坏适应算法。经编码调试,表明该程序模块是有效可行的。

通过这门课程的学习让我充分了解了内存管理的机制实现,从而更深一步的的对计算机

有了很多了解,这对于以后我们的研究和学习计算机系统起到了很重要的作用。

对于本次论文制作,自己的编程能力有所提高,对操作系统内存分配,存储空间的回收都有全新的认识。

在这次操作系统课程设计中,我使用了c++编写系统软件,对os中可变分区存储管理有了深刻的理解,但是过程中遇到了很多困难,一边做一边学,对c++有了比较多的理解。

实验中遇到很多问题,浪费了很多时间,总而言之是自己学习还不够好,不扎实,希望在以后学习中加以改善,学到更多知识。

参考文献

【1】 汤子瀛,哲凤屏,汤小丹.计算机操作系统.西安:西安电子科技大学出版社,2001.。

28 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

【2】 任爱华.操作系统实用教程.北京:清华大学出版社,2001。

29

推荐第3篇:操作系统课程设计

《操作系统》/《操作系统课程设计》课设指导书

《操作系统》 《操作系统课程设计》

指导

信息技术学院课设书

《操作系统》/《操作系统课程设计》课设指导书

《操作系统》/《操作系统课程设计》

课设项目指导书

课设项目1 磁盘调度算法程序设计

一、目的

磁盘是经常使用的一种重要的外设,对磁盘数据的寻道时间的长短直接影响机器的整体运行速度,本设计要求用C语言(或高级语言)编写程序模拟实现磁盘调度的常用算法。以加深对磁盘调度常用算法的理解和实现技巧。

二、课设要求

1)、设计一个函数完成先来先服务的磁盘调度功能。 2)、设计一个函数完成最短寻道时间优先的磁盘调度功能。 3)、设计一个函数完成电梯算法的磁盘调度功能。

三、课设设备、环境

奔腾以上计算机,装有Turbo C 2.0软件

四、课设方法及步骤

1、设计方法:

根据设计任务书的要求,画出程序设计流程图,确定程序的功能,把整个程序根据功能要求分解为各个子程序,利用TC语言分编写程序代码,然后进行上机调试、修改、进行连接,测试,写出设计总结报告。

2、设计步骤:

1)、自定义磁盘调度相关的数据结构。

2)、依据先来先服务算法(FCFS)、最短寻道优先算法(SSTF)、扫描(SCAN,也称电梯)算法的原理,编写对应函数,模拟系统的磁盘调度服务。

3)、为了更好地模拟和评价算法的性能,随机产生需寻道的磁道序列,磁道序列的首磁道为磁头的当前位置;在SCAN算法中,允许用户指定当前寻道方向。

4)、统计各算法总寻道次数和平均寻道距离;分析各算法性能,并作出评价。 5)、设计要求一人单独进行,独立完成设计,上机进行运行调试。 6)、写出课程设计报告书。

课设项目2 进程调度程序设计

一、目的

进程调度是处理机管理的核心内容。本设计要求用C语言编写和调试一个简单的进程调度程序。通过设计本可以加深理解有关进程控制块、进程队列的概念,并体会和了解最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法的具体实施办法。

二、课设要求

1)进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。

2)每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。

3)进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。

4)每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。

5)就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。

6)每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。

7)重复以上过程,直到所要进程都完成为止。

三、课设设备、环境

奔腾以上计算机,装有Turbo C 2.0软件

四、课设方法及步骤

1、设计方法:

根据设计任务书的要求,画出程序设计流程图,确定进程调度程序的功能,把整个程序根据功能要求分解为各个子程序,利用TC语言分编写程序代码,然后进行上机调试、修改、进行连接,测试,写出设计总结报告。

《操作系统》/《操作系统课程设计》课设指导书

进程调度算法参考流程图

2、设计步骤:

1)充分了解各项设计要求。深入理解有关进程控制块、进程队列的概念,并体会和了解最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法的具体实施办法。

2)、按要求对进程调度程序进行分解,根据功能将其分解成多个子模块。

3)、建立主控模块程序流程图及各功能子模块程序流程图,要求条理清楚、简单明了、功能完备。

4)、根据流程图编制主程序代码及子程序代码。要求程序设计结构清晰,简洁,便于修改和调试。

5)、上述设计要求一人单独进行,独立完成设计。 6)、设计完成后,上机进行运行调试。

7)、程序运行成功,然后进行某些功能测试,选择有实用性、特殊性的数据进行录入调试,使设计进一步得到改进并完善。

8)、打印出程序运行结果,并对结果进行分析,验证程序设计的正确性。 9)、写出课程设计报告书。

《操作系统》/《操作系统课程设计》课设指导书

课设项目3 银行家算法程序设计

一、目的

银行家算法是避免死锁的一种重要方法,本设计要求用C语言(或高级语言)编写和调试一个简单的银行家算法程序。加深了解有关资源申请、避免死锁等概念,并体会和了解死锁和避免死锁的具体实施方法。通过对这个算法的设计,让学生能够对书本知识有更深的理解,在操作和其它方面有更高的提升,同时对程序设计的水平也有所提高。

二、课设要求

设计一个n个并发进程共享m个系统资源的程序实现银行家算法。要求包含: 1)、简单的选择界面。

2)、前系统资源的占用和剩余情况。

3)、为进程分配资源,如果进程要求的资源大于系统剩余的资源,不与分配并且提示分配不成功。

4)、撤销作业,释放资源。

三、课设设备、环境

奔腾以上计算机,装有Turbo C 2.0软件

四、课设方法及步骤

1、设计方法:

根据设计任务书的要求,画出程序设计流程图,确定程序的功能,把整个程序根据功能 要求分解为各个子程序,利用TC语言分编写程序代码,然后进行上机调试、修改、进行连接,测试,写出设计总结报告。

2、设计步骤:

1)、充分了解各项设计要求。深入理解多道程序系统中,进程并发执行的资源分配问题,和系统安全状态的概念。了解资源在进程并发执行中的资源分配策略并体会和掌握银行家算法的具体实现。

2)、按要求对进程调度程序进行分解,根据功能将其分解成多个子模块。

3)、模块程序流程图及各功能子模块程序流程图,要求条理清楚、简单明了、功能完备。 4)、根据流程图编制主程序代码及子程序代码。要求程序设计结构清晰,简洁,便于修改和调试。

5)、上述设计要求一人单独进行,独立完成设计。 6)、设计完成后,上机进行运行调试。

7)、程序运行成功,然后进行某些功能测试,选择有实用性、特殊性的数据进行录入调

试,使设计进一步得到改进并完善。

8)、打印出程序运行结果,并对结果进行分析,验证程序设计的正确性。 9)、设计报告书。

3、算法描述

设Request[i] 是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源,当Pi发出资源请求后,系统按下面步骤进行检查:

1)、如果Requesti[j]

2)、如果Requesti[j]

3)、系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:

Available[j]:=Available[j]-Requesti[j]; Allocation[i,j]:=Allocation[i,j]+Requesti[j]; Need[i,j]:=Need[i,j]-Requesti[j];

4)、系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才 正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来 的资源分配状态,让进程Pi等待。

4、数据结构

银行家算法中的数据结构:

1)、可利用资源向量Available。这是一个含有n个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。

2)、最大需求矩阵Max。这是一个m*n的矩阵,它定义了系统中n个进程中每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。 3)、分配矩阵Allocation。这也是一个m*n的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。

4)、需求矩阵Need。这也是一个n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。

5)、工作数组Work.。这是一个含有n个元素的数组,它代表可以提供分配的资源数,初始值是Available中的数值,随着资源的回收,它的值也会改变,公式是 6

《操作系统》/《操作系统课程设计》课设指导书

Work[i]=Work[i]+Allocation[i]。

课设项目4 存储管理程序设计

一、目的

存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。本次设计的目的是通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。

二、课设要求

设计一个请求页式存储管理方案。并编写模拟程序实现之。要求包含: 1.过随机数产生一个指令序列,共320条指令。其地址按下述原则生成: ①50%的指令是顺序执行的;

②25%的指令是均匀分布在前地址部分; ③25%的指令是均匀分布在后地址部分; #具体的实施方法是:

A.在[0,319]的指令地址之间随机选区一起点M; B.顺序执行一条指令,即执行地址为M+1的指令;

C.在前地址[0,M+1]中随机选取一条指令并执行,该指令的地址为M’; D.顺序执行一条指令,其地址为M’+1;

E.在后地址[M’+2,319]中随机选取一条指令并执行; F.重复A—E,直到执行320次指令。 2.指令序列变换成页地址流

设:(1)页面大小为1K;

(2) 用户内存容量为4页到32页; (3) 用户虚存容量为32K。

在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:

第0条—第9条指令为第0页(对应虚存地址为[0,9]);

第10条—第19条指令为第1页(对应虚存地址为[10,19]);

。。。。。。。。。。。。。。。。。。。。。

第310条—第319条指令为第31页(对应虚存地址为[310,319]); 按以上方式,用户指令可组成32页。

3.计算并输出下述各种算法在不同内存容量下的命中率。

《操作系统》/《操作系统课程设计》课设指导书

A.FIFO先进先出的算法 B.LRR最近最少使用算法

C.OPT最佳淘汰算法(先淘汰最不常用的页地址) D.LFR最少访问页面算法 E.NUR最近最不经常使用算法

三、课设设备、环境

奔腾以上计算机,装有Turbo C 2.0软件

四、课设方法及步骤

1、设计方法:

根据设计任务书的要求,画出程序设计流程图,确定程序的功能,把整个程序根据功能要求分解为各个子程序,利用TC语言分编写程序代码,然后进行上机调试、修改、进行连接,测试,写出设计总结报告。

2、设计步骤:

1)、充分了解各项设计要求。深入理解有关页表、页面置换的概念,并体会和了解先进先出页面置换算法、先来先服务算法的具体实施办法。

2)、按要求对存储管理程序进行分解,根据功能将其分解成多个子模块。

3)、建立主控模块程序流程图及各功能子模块程序流程图,要求条理清楚、简单明了、功能完备。

4)、根据流程图编制主程序代码及子程序代码。要求程序设计结构清晰,简洁,便于修改和调试。

5)、上述设计要求一人单独进行,独立完成设计。 6)、设计完成后,上机进行运行调试。

7)、程序运行成功,然后进行某些功能测试,选择有实用性、特殊性的数据进行录入调试,使设计进一步得到改进并完善。

8)、打印出程序运行结果,并对结果进行分析,验证程序设计的正确性。 9)、写出课程设计报告书。

课设项目5 文件系统程序设计

一、目的

本设计要求用C语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。本次课程设计的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能和内部实现。

二、课设要求

要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。要求包含:

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

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

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

4)可以实现下列几条命令

LOGIN 用户登陆 DIR 列文件目录 CREATE 创建文件 DELETE 删除文件 OPEN 打开文件 CLOSE 关闭文件 READ 读文件 WRITE 写文件

5)因系统小,文件目录的检索可使用简单的线性搜索。

三、课设设备、环境

奔腾以上计算机,装有Turbo C 2.0软件

四、课设方法及步骤

1、设计方法:

《操作系统》/《操作系统课程设计》课设指导书

根据设计任务书的要求,画出程序设计流程图,确定程序的功能,把整个程序根据功能要求分解为各个子程序,利用TC语言分编写程序代码,然后进行上机调试、修改、进行连接,测试,写出设计总结报告。

2、设计步骤:

1)、充分了解各项设计要求。深入理解有关文件控制块、目录的概念,并体会和了解目录管理的具体实施办法。

2)、按要求对进程调度程序进行分解,根据功能将其分解成多个子模块。

3)、建立主控模块程序流程图及各功能子模块程序流程图,要求条理清楚、简单明了、功能完备。

4)、根据流程图编制主程序代码及子程序代码。要求程序设计结构清晰,简洁,便于修改和调试。

5)、上述设计要求一人单独进行,独立完成设计。 6)、设计完成后,上机进行运行调试。

7)、程序运行成功,然后进行某些功能测试,选择有实用性、特殊性的数据进行录入调试,使设计进一步得到改进并完善。

8)、打印出程序运行结果,并对结果进行分析,验证程序设计的正确性。 9)、写出课程设计报告书。

推荐第4篇:操作系统课程设计

1 引言

操作系统是计算机科学与技术专业的主要专业基础课和主干课。操作系统对计算机系统资源实施管理,是所有其他软件与计算机硬件的唯一接口,所有用户在使用计算机时都要得到操作系统提供的服务。

通过模拟操作系统的全部或者部分功能的实现,加深对操作系统工作原理和操作系统实现方法的理解,达到练习编程的目的,提高学生运用理论知识分析问题、解决问题的能力,为学生从事科学研究和独立负担计算机及其应用方面的工作打好扎实的基础。

0 河北大学工商学院2011级操作系统课程设计论文(设计)

2 课程设计任务及要求

2.1 设计任务

模拟采用多道程序设计方法的单用户操作系统,该操作系统包括进程管理、存储管理、设备管理、文件管理和用户接口四部分。

本部分要求实现文件的逻辑结构、文件的物理结构、目录结构、磁盘分配和回收、文件的保护和用户接口。

2.2 实现方法和原理

2.2.1文件的逻辑结构:

文件的逻辑结构采用流式结构; 文件均采用文本文件;

系统中有两种文件,一种是存放任意字符的文件,一种是可执行文件。可执行文件的内容就是模拟系统内进程的程序体。

文件中要有一种特定命令的“可执行”文件,文件中的命令非常简单,包括: x=?;

给x赋值一位数 x++;

x加1 x--;

x减1 !??;

第一个?为A,B,C中某个设备,第二个?为一位数,表示使用设备的时间(由于没有实际设备,所以无法知道设备何时工作完成,所以假定一个数,这个数随着系统时间增加而递减,减到0时,认为是设备工作完成);

end.

表示文件结束,同时将结果写入文件out,其中包括文件路径名和x的值。 2.2.2 磁盘模拟:

用一个文件disk模拟磁盘,磁盘的每个盘块64字节,模拟磁盘共有128块。第0、1块存放文件分配表,第2块存放根目录,其余存放子目录和文件。 2.2.3目录结构

目录结构采用树型目录结构,目录项内容共十六个字节。 ①目录项内容(8个字节): 目录名、文件名:3个字节;

1 河北大学工商学院2011级操作系统课程设计论文(设计)

扩展名:1个字节(可执行文件扩展名为e,目录没有扩展名); 目录、文件属性:1字节; 起始盘块号:1个字节;

文件长度:2字节(目录没有长度)。 ②根目录

根目录位置固定,为磁盘第2块,大小固定,共8项,占用模拟磁盘第2块; ③子目录

位置不固定,大小不固定。 2.2.4磁盘分配

磁盘的分配采用链接结构(显式链接)的分配方式。系统采用文件分配表方式记录磁盘空间的使用情况和链接结构的指针。

因为磁盘有占用磁盘由128块,所以文件分配表中一项需要1字节,而磁盘由128块,因而需要128项,所以模拟磁盘空间中的第0、1块被用来存放文件分配表。 2.2.5用户接口

用户接口提供用户命令接口,要求实现以下命令: 创建文件:create 拷贝文件:copy 删除文件:delete 移动文件:move 显示文件:type 编辑文件:edit 改变文件属性:change 磁盘格式化命令 format 建立目录:makdir 改变目录路径:chadir

删除空目录:rdir 删除目录:deldir(既可删除空目录又可删除非空目录)

2 河北大学工商学院2011级操作系统课程设计论文(设计)

磁盘分区命令:fdisk 运行可执行文件:可执行文件的文件名(可创建进程)。

上述命令在实际系统中都是需要建立进程才可以实现的,这里由于模拟系统的能力达不到,所以除运行可执行文件需要建立进程外,其他指令执行不必在模拟系统中建立进程,可直接执行。

注意打开文件表。 2.2.6屏幕显示

如图所示,屏幕显示要求包括:

用户命令接口,用于系统运行时用户输入命令; 磁盘目录显示,要求显示磁盘的树型目录结构;

磁盘使用情况,显示磁盘每一个磁盘块的空间是占用还是空闲。

3程序设计与实现

3.1目录结构的实现

3.1.1创建目录

#region CreateMenu(建立目录)

public void CreateMenu(string pathname,string harddisk) 3.1.2删除空目录

删除空目录首先要找到该目录,如果目录不存在,执行指令失败;如果存在,但是根

3 河北大学工商学院2011级操作系统课程设计论文(设计)

目录或非空目录显示不能删除,操作失败;若是非空子目录,则删除器目录项并回收对应空间。删除空目录的过程和删除文件的过程相似。

3.1.3删除目录

#region DeleteMenu(删除目录)

public void DeleteMenu(string pathname, string harddisk)

{

if (Search(pathname,harddisk) == 1)

{

MeageBox.Show(\"文件路径不正确!\", \"注意\", MeageBoxButtons.OK, MeageBoxIcon.Exclamation); 3.2文件 3.2.1创建文件

#region CreateFile(建立文件) public void CreateFile(string pathname, byte attribute, byte addre, char length, string harddisk) {

if (attribute == 3 || attribute == 5) {

MeageBox.Show(\"只读性质,建立失败!\", \"注意\", MeageBoxButtons.OK,

MeageBoxIcon.Exclamation);

return; } 3.2.2拷贝文件

#region CopyFile(复制文件,只复制FCB)

public void CopyFile(string pathname1, string pathname2, string harddisk)

{

string[] pnames = pathname1.Split(new char[] { \'\\\', \'.\' });

string halfpathname = pathname1.Remove(pathname1.Length1]);

UTF8Encoding utf = new UTF8Encoding(); 4 河北大学工商学院2011级操作系统课程设计论文(设计)

byte[] name = utf.GetBytes(pnames[pnames.Length1];

CreateFile(pathname2, buffer.Attribute, buffer.Addre, buffer.Length,harddisk);

}

#endregion 3.2.3删除文件 #region DeleteFile(删除文件)

public void DeleteFile(string pathname, string harddisk)

{

if(Search(pathname,harddisk)==1)

{

MeageBox.Show(\"文件路径不正确!\", \"注意\", MeageBoxButtons.OK, MeageBoxIcon.Exclamation);

return;

}

else if (Search(pathname,harddisk) == 2)

//文件存在

{

string[] pnames = pathname.Split(new char[] { \'\\\', \'.\' });

string halfpathname = pathname.Remove(pathname.Length2]);

int disknum;

if (pnames.Length == 3)

//c:\\aaa.t

{

disknum = 3;

}

else

{

disknum = Search(halfpathname,harddisk);

}

int item = FindItem(disknum, name, attribute,harddisk)[0];

int addre = FindItem(disknum, name, attribute,harddisk)[1];

byte addr = Convert.ToByte(addre);

DeleteFCB(disknum, item,harddisk);

//删除FCB

if(addr==0)

{

return; 3.2.4移动文件

#region CutFile(移动文件)

public void CutFile(string pathname1, string pathname2, string harddisk)

{

CopyFile(pathname1, pathname2,harddisk); //复制FCB到新目录下

string[] pnames = pathname1.Split(new char[] { \'\\\', \'.\' });

string halfpathname = pathname1.Remove(pathname1.Length1]);

UTF8Encoding utf = new UTF8Encoding(); 6 河北大学工商学院2011级操作系统课程设计论文(设计)

byte[] name = utf.GetBytes(pnames[pnames.Length1) + 8 * (Itemnumber - 1), SeekOrigin.Begin);

Disk.Write(buffer.Name, 0, buffer.Name.Length);

Disk.Seek(0, SeekOrigin.Current);

Disk.WriteByte(buffer.Type);

Disk.Seek(0, SeekOrigin.Current);

Disk.WriteByte(buffer.Attribute);

Disk.Seek(0, SeekOrigin.Current);

Disk.WriteByte(buffer.Addre); 7 河北大学工商学院2011级操作系统课程设计论文(设计)

Disk.Seek(0, SeekOrigin.Current);

Disk.WriteByte(Convert.ToByte(buffer.Length));

}

Disk.Close();

}

#endregion

3.2.7显示文件

#region ReadFile(读文件画节点)

public void ReadFile(TreeView treeView, ContextMenuStrip contextMenuStrip,ImageList imageList)

{

treeView.Nodes.Clear();

//删除集合中所有树节点

//重新添加树节点

treeView.ImageList = imageList;

TreeNode root = new TreeNode(\"计算机\", 0, 0);

TreeNode node_C = new TreeNode(\"本地磁盘C\", 4, 4);

TreeNode node_D = new TreeNode(\"本地磁盘D\", 4, 4);

node_C.ContextMenuStrip = contextMenuStrip;

node_D.ContextMenuStrip = contextMenuStrip;

treeView.Nodes.Add(root);

root.Nodes.Add(node_C);

root.Nodes.Add(node_D);

DrawTree(node_C, 3,\"disk1.txt\",contextMenuStrip);

DrawTree(node_D, 3, \"disk2.txt\",contextMenuStrip);

treeView.ExpandAll();

}

#endregion

4.程序运行部分截图

4.1主页面

8 河北大学工商学院2011级操作系统课程设计论文(设计)

4.2创建文件

4.3编辑文件

9 河北大学工商学院2011级操作系统课程设计论文(设计)

4.4创建目录

5 总结

在此系统我主要模拟的是文件部分。通过编写此系统,采用了c#语言。但是,在实现此系统中,一方面因为我对c#这门语言掌握的不是很熟练,另外一方面,对操作系统理解的不够深入以至于部分功能没有实现,让我发现了自己的不足,从而要在以后的学习中更加努力,不短提高自己个方面的能力。

10 河北大学工商学院2011级操作系统课程设计论文(设计)

推荐第5篇:操作系统课程设计

课程实验报告

课程名称:

操作系统原理课程设计

专业班级: 学

号: 姓

名 指导教师: 报告日期:

计算机科学与技术学院

目录

1.实验目的 ............................................................................................................................4 2.实验环境 ..........................................................................................................................4 3.实验内容 ..........................................................................................................................4 3.1 实验一 ....................................................................................................................4 3.2 实验二 ....................................................................................................................4 3.3 实验三 ....................................................................................................................5 3.4 实验四 ....................................................................................................................5 4.实验设计 ..........................................................................................................................5 4.1 实验一 ....................................................................................................................5 4.1.1 文件拷贝 ......................................................................................................5 4.1.2 并发进程分窗口显示 ....................................................................................5 4.2 实验二 ....................................................................................................................6 .....................................................................................................................................6 4.3 实验三 ....................................................................................................................6 4.4 实验四 ....................................................................................................................7 5.实验步骤 ..........................................................................................................................8 5.1 实验一 .............................................................................................................8 5.1.1 文件拷贝 ......................................................................................................8 5.1.2 并发进程分窗口显示 ....................................................................................9 5.2 实验二 ..................................................................................................................14 5.3 实验三 ..................................................................................................................15 2 5.4 实验四 ..................................................................................................................17 6.调试记录 ........................................................................................................................19 7.心得体会 ........................................................................................................................21 8.程序清单 ........................................................................................................................22 8.1实验一 ...................................................................................................................22 8.1.1 文件拷贝 ....................................................................................................22 8.1.2并发进程窗口显示 ......................................................................................23 8.2实验二 ...................................................................................................................33 8.3实验三 ...................................................................................................................34 8.4实验四 ...................................................................................................................38

1.实验目的

(1)掌握Linux操作系统的使用方法; (2)了解Linux系统内核代码结构; (3)掌握实例操作系统的实现方法。

2.实验环境

本次课程设计采用的操作系统环境是Windows

7、Ubuntu双系统,Ubuntu系统版本为15.04,内核版本是Linux 3.19。

3.实验内容

3.1 实验一

1)编写一个C程序,用fread、fwrite等库函数实现文件拷贝功能。

2)编写一个C程序,使用基于文本的终端图形编程库(curses)或图形界面(QT/GTK),分窗口显示三个并发进程的运行(一个窗口实时显示当前时间,一个窗口实时监测CPU的利用率,一个窗口做1到100的累加求和,刷新周期分别为1秒,2秒和3秒)。

3.2 实验二

4 采用编译内核的方法,添加一个新的系统调用实现文件拷贝功能 编写一个应用程序,测试新加的系统调用

3.3 实验三

采用模块方法,添加一个新的字符设备的驱动程序,实现打开/关闭、读/写等基本操作,编写一个应用程序,测试添加的驱动程序。

3.4 实验四

1)了解/proc文件的特点和使用方法。 2)监控系统状态,显示系统部件的使用情况。

3)用图形界面监控系统状态,包括CPU和内存利用率、所有进程信息等(可自己补充、添加其他功能)。

4.实验设计

4.1 实验一

4.1.1 文件拷贝

实现文件拷贝功能需要使用的函数是fopen、fgetc、fputc,由命令行参数获取2个文件名,根据其文件名和路径分别打开该2个文件,设置循环,使用fgetc和fputc函数每次从源文件复制1个字节到目的文件,直到源文件指针到文件尾,实现文件拷贝操作。 4.1.2 并发进程分窗口显示

5 使用图形界面GTK实现窗口的显示,使用fork()创建三个并发进程: pid=fork():创建子进程。

返回值:0

从子进程返回 >0

从父进程返回

exit进程自我终止,进入僵死状态 wait( ) 等待进程终止(由父进程调用) exec( ) 执行一个可执行程序(文件)。

4.2 实验二

不同的Linux内核版本编译内核和添加系统调用的方法不尽相同,在网上查阅了资料之后找到适合3.19版本内核的编译方法。

所谓系统调用,即Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用,用户可以通过系统调用命令在自己的应用程序中调用它们。其调用机制为:使用寄存器中适当的值跳转到内核中事先定义好的代码中执行:跳转到系统调用的总入口system_call,检查系统调用号,再查找系统调用表sys_call_table,调用内核函数,最后返回。

实验二目的是更改内核中系统调用模块,增加自定义函数实现文件拷贝功能。

4.3 实验三

Linux设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程,每个设备文件有两个设备号,主设备号标识驱动程序,从设备号表示使用 6 同一个设备驱动程序的不同硬件设备。

设备驱动程序的功能包括:对设备初始化和释放,把数据从内核传送到硬件和从硬件读取数据,读取应用程序传给设备文件的数据和回送应用程序请求的数据,检测和处理设备出现的错误 。

Linux支持的设备包括三种:字符设备、块设备和网络设备。 添加设备驱动程序大致需要以下几个步骤:

1.注册设备 2.定义功能函数 3.卸载设备

4.4 实验四

proc文件系统特点:

1.进程文件系统和内核文件系统组成的复合体

2.将内核数据对象化为文件形式进行存取的一种内存文件系统

3.监控内核的一种用户接口,拥有一些特殊的纯文本文件,从中可以获取系统状态信息

4.系统信息:与进程无关,随系统配置的不同而不同 5.进程信息:系统中正在运行的每一个用户级进程的信息 其中各个文件保存的信息如下: /proc/cmd/line: 内核启动的命令行 /proc/cpuinfo: CPU信息

/proc/stat: CPU的使用情况、磁盘、页面、交换、所有的中断、最后一次的启动 7 时间等

/proc/meminfo: 内存状态的有关信息

利用/proc文件获取系统状态信息,并通过GTK图形化编程将系统信息以及通过这些信息计算得出的如CPU利用率、内存使用等通过窗口显示出来。

5.实验步骤

5.1 实验一

5.1.1 文件拷贝

文件拷贝主要是利用文件指针操作,在源文件和目的文件之间进行字符的复制,拷贝之前要判断源文件是否存在以及能否打开,这需要设置一个判断语句,同时也要设置判断语句判断目的文件是否存在,若不存在需要能够创建一个目的文件,最后执行循环拷贝。

步骤如下:

1.在Linux终端使用编译命令:gcc mycopy.c -o mycopy产生可执行文件。 2.创建源文件wangzihao目的文件shaochongjun。 3.编辑源文件:

8

4.打开可执行程序:./mycopy wangzihao shaochongjun 5.查看目的文件发现已经实现拷贝:

6.若源文件不存在会报错:

5.1.2 并发进程分窗口显示

1.使用fork()函数创建三个进程,使用exec函数族实现程序的调用:

2.调用创建窗口函数init_window(),将进程中的信息在窗口中显示:

3.分别创建三个程序实现显示系统时间、CPU利用率、累加求和功能:

4.运行结果如下:

12

5.2 实验二

原内核版本:3.19.0 编译新内核版本:3.19.8 1.下载内核并解压

2.系统调用函数实现:修改kernel/sys.c文件,在文件的最后添加新的系统调用函数:sys_mycall(char* sourceFile,char* destFile) 3.设置系统调用号:修改arch/x86/syscalls/syscall_32.tbl,在最后一行添加新的系统调用号

4.添加系统调用声明到头文件 :~$ vi include/asm-generic/syscalls.h 在#endif前添

#ifndef sys_mycall asmlinkage long sys_mycall(long number); #endif

5.安装基本编译套件:apt-get install build -eential kernal-package libncurses5-dev fakeroot 6.配置内核:make menuconfig 7.编译内核:make -j4 8.安装内核:make modules_install make install 9.重启进入新的内核

10.编写测试程序测试新的系统调用:

测试结果如下:

5.3 实验三

1.编写Makefile文件:

2.编写设备功能函数:(见程序清单)

3.设备加载:make clean make

加载模块:insmod wzhdriver.ko

输入 cat /proc/devices得 设备驱动的主设备号为:

15

加载 设备,分配设备号:mknod /dev/wzhdriver c 248 0

更改操作权限:chmod 666 /dev/wzhdriver 4.运行测试程序,结果:

5.4 实验四

1系统信息页:

2进程信息页:

17

3内存资源页:

18

6.调试记录

1.在编译gtk程序时,需要添加` pkg-config --cflags --libs gtk+-3.0`.参数。 2.实验一程序过于简单,健壮性不大。

3.由于一开始没有加入刷新函数,导致实验一显示窗口数据不变化,在同学帮助下改正。

4.编译内核占用大量时间后来发现在make后添加-j4可以大大提升速度。

19

20

7.心得体会

本次课程设计主要目的是熟悉Linux系统,掌握Linux操作系统的使用方法,了解Linux系统内核代码结构,掌握实例操作系统的实现方法。由于刚开始接触Linux,实验的开始遇到了不少困难,GTK的安装和使用花费了我不少时间,并行程序是操作系统课程学过的内容,主要难点是图形化界面的设计。

实验二是耗费时间最多的,由于每个版本的内核编译方式不同,耗费了大量时间查找编译内核的方法,同时编译一次内核需要一个小时以上,不过皇天不负有心人最后我成功添加了系统调用。

添加设备驱动比较简单,主要是了解了Linux设备驱动的原理,熟悉设备驱动的安装过程。

分析/proc文件主要是搭建图形化界面,在借鉴了网上资源设计的窗口之后,我设计了简单的监控系统图形界面,其中CPU利用率以及占用曲线等需要计算。 通过本次实验我学到了很多东西,熟悉了Linux系统的使用方法,对Linux系统内核代码结构有了大致的了解,掌握了图形化界面GTK的使用,总而言之本次试验我获益匪浅。

21

8.程序清单

8.1实验一

8.1.1 文件拷贝 #include int main(int argc,char *argv[]) {

if(argc!=3)

{ printf(\"Error in argc!\\n\"); return 0;

}

FILE * fsource=NULL;

FILE * ftarget=NULL;

if( (fsource=fopen(argv[1],\"rb\"))==NULL )

{ printf(\"Fail to open source file!\\n\"); return 0;

}

if( (ftarget=fopen(argv[2],\"wb\"))==NULL )

{ printf(\"Fail to open target file!\\n\"); 22 return 0;

}

int c;

while((c=fgetc(fsource))!=EOF)

{ fputc(c,ftarget);

}

fclose(fsource);

fclose(ftarget);

return 0; } 8.1.2并发进程窗口显示

主函数:

#include #include #include int main() { pid_t time; pid_t cpu; pid_t sum; 23

if((time=fork())==-1) {

}

if(time==0) { execlp(\"./time\",0); printf(\"fork error\\n\"); return -1; }else {

if((cpu=fork())==-1) //create cpu {

} if(cpu==0) { execlp(\"./cpu\",0); printf(\"fork error\\n\"); return -1; }else 24

{ if((sum=fork())==-1) //create sum

{

printf(\"fork error\\n\");

return -1;

}

if(sum==0)

{

execlp(\"./sum\",0);

}else //father proce

{

wait(&time);

wait(&cpu);

wait(&sum);

}

}

}

} 系统时间:

25 #include #include #include #includechar t[50]; GtkWidget *label; gettime(){

time_t timep;

time (&timep);

sprintf(t,\"%s\",ctime(&timep));} void *thread(void * argc){

while(1){

gettime();

gtk_label_set_text(GTK_LABEL(label),t);

sleep(1);}

}

int main( int argc, char *argv[]) {

pthread_t id;

int i,ret;

ret=pthread_create(&id,NULL,(void *) thread,NULL); 26

GtkWidget *vbox;

GtkWidget *window;

//定义一个组装盒;

/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/

gtk_init(&argc, &argv);

/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window), \"time\");

gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

label = gtk_label_new (t);

gtk_container_add (GTK_CONTAINER (window), label);

gtk_widget_show (label);

/*开始显示窗口*/

gtk_widget_show(window);

gtk_main();

return 0; } CPU利用率: #include #include 27 #include GtkWidget* label; //the use rate of cpu char c[5]; float cpu(); void* thread(void* arg) {

} float cpu() {

FILE* fp; char buf[128]; char cpu[5]; long int user,nice,sys,idle,iowait,irq,softirq; float usage; while(1) {

} sleep(2); usage=cpu(); sprintf(c,\"the usage of cpu is %f %%\",usage); gtk_label_set_text(GTK_LABEL(label), c); 28

fp=fopen(\"/proc/stat\",\"r\"); if(fp==NULL) printf(\"error\\n\"); long int all1,all2,idle1,idle2; float usage; fgets(buf,sizeof(buf),fp);

canf(buf,\"%s%ld%ld%ld%ld%ld%ld%ld\",cpu,&user,&nice,&sys,&idle,&iowait,&irq,&softirq);

canf(buf,\"%s%ld%ld%ld%ld%ld%ld%ld\",cpu,&user,&nice,&sys,&idle,&iall1=user+nice+sys+idle+iowait+irq+softirq; idle1=idle; rewind(fp); //second sleep(1); memset(buf,0,sizeof(buf)); cpu[0]=\'\\0\'; user=nice=sys=idle=iowait=irq=softirq=0; fgets(buf,sizeof(buf),fp); 29 owait,&irq,&softirq);

} int main( int argc, char *argv[]) {

pthread_t id;

int i,ret;

ret=pthread_create(&id,NULL,(void *) thread,NULL);

GtkWidget *window;

/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/

gtk_init(&argc, &argv);

/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window), \"cpu\");

gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

label = gtk_label_new (c); usage=(float)(all2-all1-(idle2-idle1))/(all2-all1)*100; return usage; all2=user+nice+sys+idle+iowait+irq+softirq; idle2=idle; 30

gtk_container_add (GTK_CONTAINER (window), label);

gtk_widget_show (label);

/*开始显示窗口*/

gtk_widget_show(window);

gtk_main();

return 0; } 求和:

#include #include #include #includechar s[1000]; GtkWidget *label;

void *thread(void * argc){

int i,j,sum;

for(i=1,sum=0,j=1;i

sleep(3);

sum=sum+j;

j+=1;

sprintf(s,\"%d\",sum); 31

gtk_label_set_text(GTK_LABEL(label),s);

}

}

int main( int argc, char *argv[]) {

pthread_t id;

int i,ret;

ret=pthread_create(&id,NULL,(void *) thread,NULL);

GtkWidget *vbox;

GtkWidget *window;

/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/

gtk_init(&argc, &argv);

/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window), \"sum\");

gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);

gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

label = gtk_label_new (s);

gtk_container_add (GTK_CONTAINER (window), label);

//定义一个组装盒; 32

gtk_widget_show (label);

/*开始显示窗口*/

gtk_widget_show(window);

gtk_main();

return 0; } 8.2实验二

系统调用函数:

asmlinkage int sys_mycall(char* sourceFile,char* destFile) {

int source=sys_open(sourceFile,O_RDONLY,0);

int dest=sys_open(destFile,O_WRONLY|O_CREAT|O_TRUNC,0600);

char buf[4096];

mm_segment_t fs;

fs = get_fs();

set_fs(get_ds());

int i;

if(source>0 && dest>0)

{

do{

i=sys_read(source,buf,4096);

sys_write(dest,buf,i);

}while(i); 33

}

else {

printk(\"Error!\");

}

sys_close(source);

sys_close(dest);

set_fs(fs);

return 10; } 测试程序: #include #include #include

int main(int argc,char **argv) { int i=syscall(359,argv[1],argv[2]); printf(\"the %d\",i); return 1; } 8.3实验三

设备驱动:

#include #include #include 34 #include MODULE_LICENSE(\"GEL\"); MODULE_AUTHOR(\"wangzihao\"); #define DEV_NAME \"wzhdriver\" static ize_t GlobalRead(struct file *,char *,size_t,loff_t*); static ize_t GlobalWrite(struct file *,const char *,size_t,loff_t*); static int char_major = 0; static int GlobalData = 123456; struct file_operations globalchar_fops = {

.read = GlobalRead,

.write = GlobalWrite };

static int __init GlobalChar_init(void) {

int ret;

ret = register_chrdev(char_major,DEV_NAME,&globalchar_fops);

if(ret

{

printk(KERN_ALERT \"GlobalChar Reg Fail!\\n\");

} 35

else

{

printk(KERN_ALERT \"GloblaChar Reg Succe!\\n\");

char_major = ret;

printk(KERN_ALERT \"Major = %d\\n\",char_major);

}

return 0; } static void __exit GlobalChar_exit(void) {

unregister_chrdev(char_major,DEV_NAME);

printk(KERN_ALERT \"GlobalCharDev is dead now!\\n\");

return; } static ize_t GlobalRead(struct file *filp,char *buf,size_t len,loff_t *off) {

//GlobalData -= 1;

if (copy_to_user(buf,&GlobalData,sizeof(int)))

{

return -EFAULT;

}

return sizeof(int); 36 } static ize_t GlobalWrite(struct file *filp,const char *buf,size_t len,loff_t *off) {

if (copy_from_user(&GlobalData,buf,sizeof(int)))

{

return -EFAULT;

}

return sizeof(int); } module_init(GlobalChar_init); module_exit(GlobalChar_exit) 测试程序:

#include #include #include #include #define DEV_NAME \"/dev/wzhdriver\" int main() { int fd,num = 9999;

fd = open(DEV_NAME,O_RDWR,S_IRUSR | S_IWUSR); 37 if (fd

{

printf(\"Open Device Failed!\\n\");

return -1; } read(fd,&num,sizeof(int)); printf(\"The wzhdriver is %d\\n\",num); printf(\"input a number written to wzhdriver: \"); scanf(\"%d\",&num); write(fd,&num,sizeof(int)); read(fd,&num,sizeof(int)); printf(\"The char you input is %d\\n\",num);

close(fd); return 0; } 8.4实验四

#include #include #include #include #include 38 #include #include #include #include #include #include

char *txt_pid=NULL; char *txt_pid2=NULL;

char* meminfo_read(); /*内存使用情况*/ char* stat_read(); /*cpu使用率*/ char* procsum_read(); /*进程数*/

gint mem_refresh(gpointer mem_label); /*内存使用情况刷新*/ gint cpu_refresh(gpointer cpu_label);

/*cpu使用率刷新*/ gint proce_refresh(gpointer proce_label); /*进程数刷新*/

gboolean cpu_record_callback

(GtkWidget

*widget,GdkEventExpose *event,gpointer data);

39 gboolean mem_record_callback (GtkWidget *widget,GdkEventExpose *event,gpointer data);

void cpu_record_draw(GtkWidget *widget); void mem_record_draw(GtkWidget *widget);

static char temp_proce[50]; /*进程数*/ static char temp_cpu[50]; /*cpu使用率*/ static char temp_mem[50]; /*内存使用*/ static long idle,total; static int flag=0;

/*计算cpu时的数据*/ /*计算cpu使用率时启动程序的标志*/

/*计算单个进程cpu使用率时使用的标志*/ static int flag1=0;

static long mem_total; static long mem_free;

/*内存总大小*/ /*空闲内存*/ static long long ustime[32768]; /*前一次记录的用户态和核心态的总时间*/ static long mtime[32768]; /*前一次记录的时刻*/ static float cpu_used_percent=0;

/*cpu使用率*/ static int cpu_start_position=15; /*绘制cpu移动的线条*/ static float cpu_data[66]; static int flag2=0;

/*cpu历史数据*/

/*初始化cpu_data数组中数据的标志*/ static int cpu_first_data=0; /*第一个数据,既最早的数据,下一个要淘汰的数据 40 */ static float mem_data[66]; /*cpu历史数据*/ static int flag3=0;

/*初始化cpu_data数组中数据的标志*/ static int mem_first_data=0; /*第一个数据,既最早的数据,下一个要淘汰的数据*/ static int mem_start_position=15; /*绘制内存移动的线条*/

static GtkWidget *cpu_record_drawing_area;

static GtkWidget *mem_record_drawing_area;

static GtkWidget *notebook; /////////////////////////////////////////////

void kill_proc(void) {

char buf[20]; sprintf(buf,\"kill -9 %s\",txt_pid);

/*笔记本*/

system(buf); }

41 gint delete_event( GtkWidget *widget,

GdkEvent *event,

gpointer

data ) {

gtk_main_quit ();

return FALSE; }

char *get_cpu_name(char *_buf1) {

FILE * fp; int i=0; char *buf1=_buf1;

fp=fopen(\"/proc/cpuinfo\",\"r\"); for(i=0;i

char *get_cpu_type(char *_buf2) {

FILE * fp; int i=0; char *buf2=_buf2;

fp=fopen(\"/proc/cpuinfo\",\"r\"); for(i=0;i

char *get_cpu_f(char *_buf3) {

FILE * fp; int i=0; char *buf3=_buf3;

fp=fopen(\"/proc/cpuinfo\",\"r\"); for(i=0;i

char *get_cache_size(char *_buf4) {

FILE * fp; int i=0; char *buf4=_buf4;

fp=fopen(\"/proc/cpuinfo\",\"r\"); for(i=0;i

} fclose(fp); return buf4; char *get_system_type(char *_buf1) { FILE * fp;

int i=0;

//fp=fopen(\"/proc/version\",\"r\");

fp=fopen(\"/etc/iue\",\"r\");

fgets(buf1,256,fp);

for(i=0;i

buf1[i]=\'\\0\';

fclose(fp);

return buf1; }

char *get_system_version(char *_buf2) 46 { FILE * fp;

int i=0;

int j=0;

fp=fopen(\"/proc/version\",\"r\");

fgets(buf2,256,fp);

for(i=0,j=0;i

buf2+=i;

for(i=0;i

buf2[i+1]=\'\\0\';

fclose(fp);

return buf2; }

char *get_gcc_version(char *_buf3) { 47 FILE * fp;

int i=0;

int j=0;

fp=fopen(\"/proc/version\",\"r\");

fgets(buf3,256,fp);

for(i=0,j=0;i

buf3+=i;

for(i=0;i

buf3[i+1]=\'\\0\';

fclose(fp);

return buf3; }

void get_proc_info(GtkWidget *clist,int *p,int *q,int *r,int *s) {

DIR *dir; 48

struct dirent *ptr;

int i,j;

FILE *fp;

char buf[1024];

char _buffer[1024];

char *buffer=_buffer;

char *buffer2;

char proc_pid[1024];

char proc_name[1024];

char proc_stat[1024];

char proc_pri[1024];

char proc_takeup[1024];

char text[5][1024];

gchar *txt[5];

gtk_clist_set_column_title(GTK_CLIST(clist),0,\"PID\");

gtk_clist_set_column_title(GTK_CLIST(clist),1,\"名称\");

gtk_clist_set_column_title(GTK_CLIST(clist),2,\"状态\"); gtk_clist_set_column_title(GTK_CLIST(clist),3,\"优先级\"); gtk_clist_set_column_title(GTK_CLIST(clist),4,\"占用内存\");

gtk_clist_set_column_width(GTK_CLIST(clist),0,50);

gtk_clist_set_column_width(GTK_CLIST(clist),1,100); 49

推荐第6篇:操作系统课程设计

操作系统课程设计

注意事项:

0.请每位同学必须按时提交课程设计报告(包括电子版和纸质版),算入期末成绩

1.在三个题目中选择一个

2.如果选择题目

(一)进程调度算法,要求实现其中2个以上(包括2个)进程调度算法 3.如果选择题目

(二)银行家算法,要求能够判断系统的安全状态

4.如果选择题目

(三)页面调度算法,要求实现其中2个以上(包含2个)进程调度算法 5.报告应包含算法分析、实验截图、核心算法源代码,请各位同学认真对待,独立完成 6.提交要求:电子版(包括实验程序)请发至ropeal@163.com,纸质版请班长收齐,由班长统一在课堂上提交(并提交未交人员名单),截止时间第16周周三(2014.1.31) 7.格式要求:

7.1 A4纸10页左右

7.2 封面请注明班级、姓名、学号、所选题目

7.3 电子版发送时,请打包成一个文件,将文件名设置为:学号+姓名+题目名称(如20130000张三进程调度算法课程设计),邮件主题同文件名

一、进程调度算法

1.1 实验目的: a、设计进程控制块PCB表结构,模拟实现进程调度算法:FIFO,静态优先级调度,时间片轮转调度,多级反馈队列调度。(实现其中之二)。* b、建立进程就绪队列。对不同算法编制入链子程序。 c、编写一进程调度程序模拟程序。模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。 * 由用户输入进程名和进程长度,然后按照短进程优先的进程处理顺序给出进程的排序。

1.2 实验原理 调度算法是指:根据系统的资源分配策略所规定的资源分配算法。 1.2.1 先来先服务和短作业(进程)优先调度算法

1.先来先服务调度算法。先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度, 也可用于进程调度。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。由此可知,本算法适合于CPU繁忙型作业, 而不利于I/O繁忙型的作业(进程)。

2.短作业(进程)优先调度算法。短作业(进程)优先调度算法(SJ/PF)是指对短作业或短进程优先调度的算法,该算法既可用于作业调度, 也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。 1.2.2 高优先权优先调度算法

1.优先权调度算法的类型。为了照顾紧迫性作业,使之进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。 此算法常被用在批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度,还可以用于实时系统中。当其用于作业调度, 将后备队列中若干个优先权最高的作业装入内存。当其用于进程调度时,把处理机分配给就绪队列中优先权最高的进程,此时, 又可以进一步把该算法分成以下两种: 1)非抢占式优先权算法

2)抢占式优先权调度算法(高性能计算机操作系统)

2.优先权类型 。对于最高优先权优先调度算法,其核心在于:它是使用静态优先权还是动态优先权, 以及如何确定进程的优先权。 3.高响应比优先调度算法

为了弥补短作业优先算法的不足,我们引入动态优先权,使作业的优先等级随着等待时间的增加而以速率a提高。 该优先权变化规律可描述为:优先权=(等待时间+要求服务时间)/要求服务时间;即 =(响应时间)/要求服务时间 1.2.3 基于时间片的轮转调度算法

1.时间片轮转法。时间片轮转法一般用于进程调度,每次调度,把CPU分配队首进程,并令其执行一个时间片。 当执行的时间片用完时,由一个记时器发出一个时钟中断请求,该进程被停止,并被送往就绪队列末尾;依次循环。 2.多级反馈队列调度算法 多级反馈队列调度算法多级反馈队列调度算法,不必事先知道各种进程所需要执行的时间,它是目前被公认的一种较好的进程调度算法。 其实施过程如下:

1) 设置多个就绪队列,并为各个队列赋予不同的优先级。在优先权越高的队列中, 为每个进程所规定的执行时间片就越小。

2) 当一个新进程进入内存后,首先放入第一队列的末尾,按FCFS原则排队等候调度。 如果他能在一个时间片中完成,便可撤离;如果未完成,就转入第二队列的末尾,在同样等待调度„„ 如此下去,当一个长作业(进程)从第一队列依次将到第n队列(最后队列)后,便按第n队列时间片轮转运行。 3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1到第(i-1)队列空时, 才会调度第i队列中的进程运行,并执行相应的时间片轮转。 4) 如果处理机正在处理第i队列中某进程,又有新进程进入优先权较高的队列, 则此新队列抢占正在运行的处理机,并把正在运行的进程放在第i队列的队尾。

1.3 实验要求

a、使用模块化设计思想来设计; b、给出算法的流程图或伪码说明。 c、学生可按照自身条件,随意选择采用的算法,(例如:采用冒泡法编写程序,实现短进程优先调度的算法)

d、进程调度程序模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。

1.4 算法简析 a、每个进程可有三个状态,并假设初始状态为就绪状态。 b、为了便于处理,程序中的某进程运行时间以时间片为单位计算。 各进程的优先数或轮转时间数以及进程需运行的时间片数的初始值均由用户给定。 c、在优先数算法中,优先数可以先取值为(50-该进程所需时间),进程每执行一次,优先数减3,CPU时间片数(CPUtime)加1, * 进程还需要的时间片数(needtime)减1。在时间片轮转算法中,采用固定时间片

(即:每执行一次进程,该进程的执行时间片数为已执行了2个单位),这时,CPU时间片(CPUtime)数加2, * 进程还需要的时间片数(needtime)减2,并排列到就绪队列的尾上。

d、对于遇到优先数一致的情况,采用FIFO策略解决。

二、银行家算法

2.1 概述

2.1.1 设计目的

1、了解多道程序系统中,多个进程并发执行的资源分配。

2、掌握死锁的产生的原因、产生死锁的必要条件和处理死锁的基本方法。

3、掌握预防死锁的方法,系统安全状态的基本概念。

4、掌握银行家算法,了解资源在进程并发执行中的资源分配策略。

5、理解死锁避免在当前计算机系统不常使用的原因

2.2 关于死锁

2.2.1 死锁概念:

在多道程序系统中,虽可借助于多个进程的并发执行,来改善系统的资源利用率,提高系统的吞吐量,但可能发生一种危险━━死锁。所谓死锁(Deadlock),是指多个进程在运行中因争夺资源而造成的一种僵局(Deadly_Embrace),当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。一组进程中,每个进程都无限等待被该组进程中另一进程所占有的资源,因而永远无法得到的资源,这种现象称为进程死锁,这一组进程就称为死锁进程。

2.2.2 关于死锁的一些结论:

参与死锁的进程最少是两个(两个以上进程才会出现死锁)

参与死锁的进程至少有两个已经占有资源

参与死锁的所有进程都在等待资源

参与死锁的进程是当前系统中所有进程的子集

注:如果死锁发生,会浪费大量系统资源,甚至导致系统崩溃。

2.2.3 资源分类:

永久性资源: 可以被多个进程多次使用(可再用资源),分为:可抢占资源与不可抢占资源

临时性资源:只可使用一次的资源;如信号量,中断信号,同步信号等(可消耗性资源)

“申请--分配--使用--释放”模式

2.2.4 产生死锁的四个必要条件:

1、互斥使用(资源独占)

一个资源每次只能给一个进程使用

2、不可强占(不可剥夺)

资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放

3、请求和保持(部分分配,占有申请)

一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才是动态申请,动态分配)

4、循环等待

存在一个进程等待队列

{P1 , P2 , „ , Pn},

其中P1等待P2占有的资源,P2等待P3占有的资源,„,Pn等待P1占有的资源,形成一个进程等待环路

2.2.5 死锁的解决方案 1 产生死锁的例子

申请不同类型资源产生死锁

P1: „

申请打印机 申请扫描仪 使用

释放打印机 释放扫描仪 „ P2: „

申请扫描仪 申请打印机 使用

释放打印机 释放扫描仪 „

申请同类资源产生死锁(如内存)

设有资源R,R有m个分配单位,由n个进程P1,P2,„,Pn(n >m)共享。假设每个进程对R的申请和释放符合下列原则: * 一次只能申请一个单位 * 满足总申请后才能使用 * 使用完后一次性释放

m=2,n=3 资源分配不当导致死锁产生

2死锁预防: 定义:在系统设计时确定资源分配算法,保证不发生死锁。具体的做法是破坏产生死锁的四个必要条件之一

①破坏“不可剥夺”条件

在允许进程动态申请资源前提下规定,一个进程在申请新的资源不能立即得到满足而变为等待状态之前,必须释放已占有的全部资源,若需要再重新申请 ②破坏“请求和保持”条件

要求每个进程在运行前必须一次性申请它所要求的所有资源,且仅当该进程所要资源均可满足时才给予一次性分配 ③破坏“循环等待”条件 采用资源有序分配法:

把系统中所有资源编号,进程在申请资源时必须严格按资源编号的递增次序进行,否则操作系统不予分配。

2.2.6 安全状态与不安全状态

安全状态: 如果存在一个由系统中所有进程构成的安全序列P1,„Pn,则系统处于安全状态。一个进程序列{P1,„,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j

不安全状态:不存在一个安全序列,不安全状态一定导致死锁。

2.3 数据结构设计

1.可利用资源向量矩阵AVAILABLE。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果AVAILABLE [j]= K,则表示系统中现有R类资源K个

2.最大需求矩阵MAX。这是一个n*m的矩阵,用以表示每一个进程对m类资源的最大需求。如果MAX [i,j]=K,则表示进程i需要R类资源的数目为K。

3.分配矩阵ALLOCATION。这也是一个n*m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果ALLOCATION [i,j]=K,则表示进程i当前已分得R类资源的数目为K。

4.需求矩阵NEED。这也是一个n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果NEED [i,j]=K,则表示进程i还需要R类资源K个,才能完成其任务。 上述矩阵存在下述关系:

NEED [i,j]= MAX[i,j]﹣ ALLOCATION[i,j]

2.4 算法的实现 2.4.1 初始化 由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。 2.4.2 银行家算法

在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。

银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。 (1)如果REQUEST [cusneed] [i]

(2)如果REQUEST [cusneed] [i]

2.4.3 安全性检查算法

(1)设置两个工作向量Work=AVAILABLE;FINISH (2)从进程集合中找到一个满足下述条件的进程,

FINISH==false; NEED

Work+=ALLOCATION; Finish=true; GOTO 2 (4)如所有的进程Finish= true,则表示安全;否则系统不安全。

三、页面调度算法 3.1 实验名称

页式虚拟存储管理:页面调度算法 3.2 实验目的

页式虚拟存储器实现的一个难点是设计页面调度(置换)算法,即将新页面调入内存时,如果内存中所有的物理页都已经分配出去,就要按某种策略来废弃某个页面,将其所占据的物理页释放出来,供新页面使用。本实验的目的是通过编程实现几种常见的页面调度(置换)算法,加深读者对页面思想的理解。 3.3 实验原理

页面调度算法

目前有许多页面调度算法,本实验主要涉及先进先出调度算法、最近最少调度算法、最近最不常用调度算法。本实验使用页面调度算法时作如下假设,进程在创建时由操作系统为之分配一个固定数目物理页,执行过程中物理页的数目和位置不会改变。也即进程进行页面调度时只能在分到的几个物理页中进行。

下面对各调度算法的思想作一介绍。

先进先出调度算法

先进先出调度算法根据页面进入内存的时间先后选择淘汰页面,先进入内存的页面先淘汰,后进入内存的后淘汰。本算法实现时需要将页面按进入内存的时间先后组成一个队列,每次调度队首页面予以淘汰。

最近最少调度算法

先进先出调度算法没有考虑页面的使用情况,大多数情况下性能不佳。根据程序执行的局部性特点,程序一旦访问了某些代码和数据,则在一段时间内会经常访问他们,因此最近最少用调度在选择淘汰页面时会考虑页面最近的使用,总是选择在最近一段时间以来最少使用的页面予以淘汰。算法实现时需要为每个页面设置数据结构记录页面自上次访问以来所经历的时间。

最近最不常用调度算法

由于程序设计中经常使用循环结构,根据程序执行的局部性特点,可以设想在一段时间内经常被访问的代码和数据在将来也会经常被访问,显然这样的页面不应该被淘汰。最近最不常用调度算法总是根据一段时间内页面的访问次数来选择淘汰页面,每次淘汰访问次数最少的页面。算法实现时需要为每个页面设置计数器,记录访问次数。计数器由硬件或操作系统自动定时清零。

缺页调度次数和缺页中断率、缺页置换率计算

缺页中断次数是缺页时发出缺页中断的次数。

缺页中断率=缺页中断次数/总的页面引用次数*100%

缺页调度次数是调入新页时需要进行页面调度的次数

缺页置换率=缺页调度次数/总的页面引用次数*100% 3.4 实验内容

(1)设计程序实现以上三种页面调度算法,要求:

①.可以选择页面调度算法类型;

②.可以为进程设置分到物理页的数目,设置进程的页面引用情况,可以从键盘输入页面序列,也可从文件中读取;

③.随时计算当前的页面调度次数的缺页中断率;

④.使用敲键盘或响应WM-TIMER的形式模仿时间的流逝;

⑤.以直观的的形式将程序的执行情况显示在计算机屏幕上;

⑥.存盘及读盘功能,可以随时将数据存入磁盘文件,供以后重复实验时使用。

(2)假定进程分配到3个物理块,对于下面的页面引用序列: (test.txt)

7-0-1-2-0-3-0-4-2-3-0-3-2-1-2-0-1-7-0-1

请分别用先进和先出调度算法,最近最少用调度算法,最近最不常用调度算法计算缺页中断次数,缺页中断率和缺页调度次数、缺页置换率。

再假定进程分配到

4、5个物理块,重复本实验。

(3)假定进程分配到3个物理块,对于下面的页面引用序列: (test2.txt)

4-3-2-1-4-3-5-4-3-2-1-5-0-7-3-8-9-0-2-1-4-7-3-9

请分别用先进先出调度算法、最近最少用调度算法,最近最不常用调度算法计算缺页中断次数,缺页中断率和缺页调度次数、缺页置换率。

再假定进程分配到

4、5个物理块,重复本实验。

(4)假定进程分配到3个物理块,使用程序的动态页面序列生成算法,生成一个页面序列,将此序列存入磁盘文件。再从磁盘文件读入该序列,用程序分别计算三种算法下的缺页中断次数、缺页中断率和缺页调度次数、缺页置换率。

推荐第7篇:《操作系统课程设计》教学大纲

操作系统课程设计大纲

课程名称:操作系统课程设计(Operating System Curriculum Design) 课程编码: 学 分:1 总 学 时:1周

适用专业:计算机科学与技术专业

先修课程:程序设计语言基础、操作系统

一、课程设计教学目的及基本要求

1、掌握操作系统基本理论与管理方式

2、掌握以编写程序的方法与操作系统交互

3、了解操作系统内核的添加和裁剪的一般方法

二、课程设计安排

流程:

 问题分析及解决方案确定;  形成编程思路;

 使用具体语言实现算法;  上机调试程序;  编写课程设计报告

三、课程设计指南

课程设计题目可以在老师的指导下自行选题,也可以由老师指定题目。 选题大方向有2个:基于os的编程;基于开放源代码的操作系统的内核的添加和裁剪。 以下列举若干具体选题方向共参考:

1、进程间的同步与互斥

2、进程与线程

3、虚拟存储器的工作原理以及虚拟页式存储管理中的页面置换算法

4、进程调度算法模拟编程

5、观察Linux的行为

6、进程间通信

7、理解和增加Linux系统调用

8、内核模块编程

9、文件系统编程

10、设备驱动程序

11、父进程子进程控制

12、消息的发送与接收

13、磁盘空间管理

14、鼠标键盘控制

15、银行家算法

16、基于linux的proc文件系统编程

17、网络通讯编程

18、shell编程

四、课程设计参考资料

 费翔林等,Linux操作系统实验教程,高等教育出版社,2009  罗宇,楮瑞等.操作系统课程设计.机械工业出版社,2005  冉林仓.Windows API编程.清华大学出版社,2005  Arnold Robbins.Linux程序设计.机械工业出版社,2005

五、考核及成绩评定

依据学生在设计过程中的表现、设计题目算法的合理性、编程质量、说明书撰写规范程度及答辩情况,按照一定的计权方法,综合进行评定。课程设计成绩分为优秀、良好、中等、及格、不及格五个等级

推荐第8篇:4100225操作系统课程设计

计算机与通信工程学院

计算机操作系统课程设计

学 号: 姓 名: 提交日期: 成 绩:

4100225 李彤 2013-01-10

第一部分:基于互斥量mutexes的线程互斥

一、设计任务

在Linux环境下实现,一个线程从终端接收用户的输入,另一个线程显示该字符串并清空用于输入的数组,用互斥量mutexes保证,在同一时刻只能有一个线程存取该字符串数组。

二、源代码

1.Linux代码

#include #include #include #include

sem_s; int data;

void write_data(int *a) {

data=*a;

printf(\"write data1\");

sem_post(&s); }

void read_data(void) {

sem_wait(&s);

int product;

product=data[0]*data[1];

printf(\"输出:%d*%d=%d\\n\",data); }

int main(void) {

sem_init(&s,0,0);

int a=1;

pthread_create(&t1,NULL,(void *)operate,NULL);

pthread_create(&t2,NULL,(void *)operate,&a);

pthread_join(t1,NULL);

pthread_join(t2,NULL); }

2.Windows代码

#include #include using namespace std;

string a; int s=1;

void write() { if(s=1)

s=s-1,

cout

cin>>a,

s=s+1; else cout

void read() { if(s=1) {

s=s-1;

cout

s=s+1; } else cout

system(\"pause\"); }

void main() { int choose; cout

cin>>choose;

if(choose==3)

cout

write(); else if(choose==2)

read();

main(); }

三、运行结果

第二部分:进程管理器

一、设计任务

在Linux或Window系统环境下,实现一个系统进程管理器,能够显示当前系统的活动进程信息(进程名、用户、优先级、内存使用等),并能结束或创建特定进程。可参考Window下“任务管理器”功能。

二、源代码

#include #include #include #define NULL 0 int shumu=0; //进程的内容结构体 struct node { int a; char ch; }; //进程PCB结构体 struct jincheng { int pid; int youxian; float luntime; float zhantime; char zhuangtai;//a表示执行,b表示动态就绪

node *neirong; struct jincheng *next; };

struct jincheng *neijin,*neizhi,*p,*q;

//创建新进程 int creat() { int i; if(shumu>20) {

printf(\"内存已满请先换出进程!\\n\");

i=-1;

return i; } else {

if(neijin==NULL)//如果就绪队列中没有进程的话

{

p=(jincheng*)malloc(sizeof(jincheng));

printf(\"请输入新进程的名字(数字):\\n\");

scanf(\"%d\",&p->pid);

printf(\"请输入新进程的优先级:(数字)\\n\");

scanf(\"%d\",&p->youxian);

p->luntime=3.5;

p->zhantime=3;

p->neirong=(node*)malloc(sizeof(node));

p->neirong=NULL;

p->zhuangtai=\'b\';//新建进程的状态设置为“就绪”

p->next=NULL;

neijin=p;

shumu++;

i=1;

}

else//如果就绪队列不是空队列

{

p=neijin;

while(p->next!=NULL)

{

p=p->next;//p一直指向就绪队列的队尾

}

q=(jincheng*)malloc(sizeof(jincheng));

q->next=p->next;

p->next=q;//在就绪队列的队尾加入新建的进程

printf(\"请输入新进程的名字(数字):\\n\");

scanf(\"%d\",&q->pid);

printf(\"请输入新进程的优先级:(数字)\\n\");

scanf(\"%d\",&q->youxian);

q->luntime=3.5;

q->zhantime=3;

q->neirong=(node*)malloc(sizeof(node));

q->neirong=NULL;

q->zhuangtai=\'b\';//新建进程的状态设置为就绪

shumu++;

i=1;

} } return i; }

//换出进程

void huanchu(int a) { p=neijin; while(p->pid!=a&&p!=NULL) {

q=p;

p=p->next; } if(p==NULL) {

printf(\"该进程不在内存里!\\n\");

return; } if(p==neijin) {

neijin=neijin->next; } else {

q->next=p->next;//把目标进程从就绪队列中移出来

} }

//结束进程 void jieshu() {

neizhi->next=NULL; printf(\"运行的进程已经结束!\\n\"); return; }

//创建新进程后与正在运行进程比较优先级并根据优先级判断谁该占用处理机 int bijiao() { int i,j; p=neijin; while(p!=NULL) {

q=p;

p=p->next;//q指向进程的末尾,即新建的进程

} i=q->youxian;//i代表新进进程的优先级

j=neizhi->next->youxian;//j代表正在执行进程的优先级

if(i>j)//如果新建的进程的优先级高于正在执行程序的优先级

{

p=neijin;

if(p==q)//就绪队列的进程中只有一个进程

{

neijin=neizhi->next;

p->neirong=(node*)malloc(sizeof(node));

p->neirong->a=9;

p->neirong->ch=\'c\';

neizhi->next=p;//把处理机交给优先级高的新进程

return 1;

}

else

{

while(p->next!=q)

{

p=p->next;

}//执行完后p指针在q指针前面

p->next=neizhi->next;//将正在执行的进程放置p的后面

q->neirong=(node*)malloc(sizeof(node));

q->neirong->a=9;

q->neirong->ch=\'c\';

neizhi->next=q;//将q放置在正在执行列表中,把处理机交给优先级高的进程

neizhi->next->next=NULL;

return 1;

} } else

return -1; }

//从活动就绪进程队列中找到一个优先级最高的进程并为它分配处理机 int zhixing() { int i,j; p=neijin; if(neizhi->next!=NULL) {

return -1; } i=neijin->youxian; p=neijin->next; while(p!=NULL) {

j=p->youxian;

if(i>=j)

{

p=p->next;

}

if(i

{

i=p->youxian;

p=p->next;

} } if(neijin->youxian==i) {

neijin->neirong=(node*)malloc(sizeof(node));

neijin->neirong->a=9;

neijin->neirong->ch=\'c\';

neizhi->next=neijin;

neijin=neijin->next;

neizhi->next->next=NULL; } else {

p=neijin;

while(i!=p->youxian)

{

q=p;

p=p->next;

}// q是p前面的指针

p->neirong=(node*)malloc(sizeof(node));

p->zhuangtai=\'a\';

p->neirong->a=9;

p->neirong->ch=\'c\';

neizhi->next=p;//将p放入执行列表

q->next=p->next;//将优先级高的节点舍去

} return 1; }

//查看进程 void chakan() { p=neizhi->next; printf(\"该执行进程的名字为:%d\\n\",p->pid); printf(\"该执行进程的的优先级:%d\\n\",p->youxian); printf(\"该执行进程的轮转时间为:%f\\n\",p->luntime); printf(\"该执行进程占用cpu的时间为:%f\\n\",p->zhantime); printf(\"该执行的进程内容为:\\n\"); printf(\"%d \",p->neirong->a); printf(\"%c\",p->neirong->ch); printf(\"\\n\"); }

//进程通信

void tongxin(int a) { q=neijin; while(q->pid!=a&&q!=NULL) {

q=q->next; }//q为id为a的进程

if(q==NULL) {

printf(\"所输入的进程不在内存中!\\n\");

return; }

p=neizhi->next;//p为正在执行的进程

q->neirong=(node*)malloc(sizeof(node)); q->neirong->a=p->neirong->a; q->neirong->ch=p->neirong->ch;//将正在执行的进程内容复制给id为a的进程

printf(\"通信成功!\\n\"); return; }

//主函数 void main() { int zhixing();//定义函数

void jieshu();//定义函数

void chakan();//定义函数

void tongxin(int);//定义函数

neizhi=(jincheng*)malloc(sizeof(jincheng)); neizhi->next=NULL; neijin=(jincheng*)malloc(sizeof(jincheng));

neijin->next=NULL;

neijin->pid=1; neijin->youxian=6; neijin->luntime=3.5; neijin->zhantime=3;

neijin->neirong=(node*)malloc(sizeof(node)); neijin->neirong=NULL; neijin->zhuangtai=\'b\'; shumu++; p=(jincheng*)malloc(sizeof(jincheng)); p->next=neijin->next; neijin->next=p;

p->pid=2; p->youxian=5; p->luntime=3.5; p->zhantime=3; p->neirong=(node*)malloc(sizeof(node)); p->neirong=NULL; p->zhuangtai=\'b\'; shumu++;

q=(jincheng*)malloc(sizeof(jincheng)); q->next=p->next; p->next=q; q->pid=3; q->youxian=4; q->luntime=3.5; q->zhantime=3; q->neirong=(node*)malloc(sizeof(node)); q->neirong=NULL; q->zhuangtai=\'b\'; shumu++; int i,n=1; int k,j,s; j=zhixing(); int creat(); while(n==1) {

printf(\"********************************************\\n\");

printf(\"*

进程演示系统

*\\n\");

printf(\"********************************************\\n\");

printf(\"

1.创建新的进程

2.查看运行进程 \\n\");

printf(\"

3.换出某个进程

4.结束运行进程 \\n\");

printf(\"

5.进程之间通信

6.退出系统 \\n\");

printf(\"********************************************\\n\");

printf(\"请选择(1~6)\\n\");

scanf(\"%d\",&i);

switch(i)

{

case 1:k=creat();

if(k==1)

printf(\"进程创建成功!\\n\");

if(neijin->next==NULL)

{

printf(\"由于只有一个进程所以为它分配处理机.\\n\");

neizhi->next=neijin;

neijin->neirong=(node*)malloc(sizeof(node));

neijin->neirong->a=3;

neijin->neirong->ch=\'c\';

neijin=NULL;

continue;

}

k=bijiao();

if(k==1)

{

printf(\"由于新进程的优先级高于正在执行的进程所以正在执行的\\n\");

printf(\"进程让出处理机交给新进程,而它变为活动就绪!\\n\");

}

if(k!=1)

printf(\"新进程的优先级低于正在运行的进程所以它只有等待!\\n\");

break;

case 2:

if(neizhi->next==NULL)

{

printf(\"没有进程处于执行状态!\\n\");

continue;

}

chakan();break;

case 3:

if(neijin==NULL)

{

printf(\"内存中已经没有处于活动就绪的进程了请创建!\\n\");

continue;

}

printf(\"已有处于活动就绪进程的名字为:\\n\");

p=neijin;

printf(\"(\");

while(p!=NULL)

{

printf(\"%d \",p->pid);

p=p->next;

}

printf(\")\\n\");

printf(\"请输入要换出的处于活动就绪进程的名字\\n\");

scanf(\"%d\",&s);

huanchu(s);

if(neijin==NULL)

printf(\"内存中已经没有活动就绪进程!\\n\");

else

{

printf(\"已有处于活动就绪进程的名字为:\\n\");

p=neijin;

printf(\"(\");

while(p!=NULL)

{

printf(\"%d \",p->pid);

p=p->next;

}

printf(\")\\n\");

}

break;

case 4:

if(neizhi->next==NULL)

{

printf(\"没有处于执行状态的进程!\\n\");

continue;

}

jieshu();

if(neijin==NULL)

{

printf(\"已经没有处于活动就绪的进程请创建!\\n\");

continue;

}

j=zhixing();

if(j==1)

{ printf(\"已为一个动态就绪进程中优先级最高的进程分配处理器!\\n\");

}

break;

case 5:

if(neijin==NULL)

{

printf(\"内存中已经没有处于活动就绪的进程了请创建!\\n\");

continue;

}

if(neizhi->next==NULL)

{

printf(\"没有处于执行状态的进程!\\n\");

continue;

}

printf(\"请输入要与正在运行的进程进行进程通讯的进程名字\\n\");

scanf(\"%d\",&s);

tongxin(s);

break;

case 6:exit(0);

default:n=0;

} } }

三、运行结果

推荐第9篇:操作系统课程设计文件系统

模拟一个简单二级文件管理系统

设计目的:通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部功能和实现过程的理解。

设计内容:模拟一个简单二级文件管理系统

一、实验内容描述 1 实验目标

本实验的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现.2 实验要求

为DOS系统设计一个简单的二级文件系统.要求做到以下几点: ①可以实现下列命令: login 用户登录 dir 列文件目录 create 创建文件 delete 删除文件 open 打开文件 close 关闭文件 read 读文件 write 写文件

②列目录时要列出文件名、物理地址、保护码和文件长度.③源文件可以进行读写保护.

二、程序主要内容

1设计思路

程序中要求每个用户在登陆后才可对其拥有的文件进行操作,用户对于其他用户的文件无操作权.文件操作包括浏览、创建、删除、打开、关闭、阅读、写入、修改模式.其他操作包括新建用户、帮助、用户登入、用户登出、退出系统.在程序文件夹下有个名为“file”的系统根目录,此目录下包括:一个名为“mfd”的文件,记录所有注册过的帐号及密码;用户文件,以用户名作为文件名,内容为其拥有的文件名及属性;一个名为“keiji”的文件夹.“keiji”文件夹中包括:“file.p”指针文件,记录所有已用的物理地址;一些以物理地址为名的文件,内容为文件内容.2 数据结构

file结构体系统文件数据结构:

fpaddrint,文件的物理地址、flengthint,文件长度、fmodeint,文件模式 0.只读;1.可写;2.可读写;3.保护、fname[]char,文件名; filemode结构体文件状态数据结构:

isopenint,文件当前状态,0.关闭;1.打开、modeint,文件模式 0.只读;1.可写;2.可读写;3.初始化;

user结构体用户信息数据结构:

uname[]char,用户名、upaword[]char,用户密码; userfile结构体用户文件数据结构:

uname[]char,用户名、ufile[]file,用户拥有的文件数组.

代码:

#include

#include

#include

#include

#include

#define MaxUser 100

//定义最大MDF主目录文件

#define MaxDisk 512*1024

//模拟最大磁盘空间

#define commandAmount 12

//对文件操作的指令数

//存储空间管理有关结构体和变量

char disk[MaxDisk];

//模拟512K的磁盘存储空间

typedef struct distTable //磁盘块结构体

{

int maxlength;

int start;

int useFlag;

distTable *next;

}diskNode;

diskNode *diskHead;

struct fileTable

//文件块结构体

{

char fileName[10];

int strat;

//文件在磁盘存储空间的起始地址

int length;

//文件内容长度

int maxlength;

//文件的最大长度

char fileKind[3];

//文件的属性——读写方式

struct tm *timeinfo;

bool openFlag;

//判断是否有进程打开了该文件

//fileTable *next;

};

//两级目录结构体

typedef struct user_file_directory //用户文件目录文件UFD

{

//char fileName[10];

fileTable *file;

user_file_directory *next;

}UFD;

//UFD *headFile;

typedef struct master_file_directory //主文件目录MFD

{

char userName[10];

char paword[10];

UFD *user;

}MFD;

MFD userTable[MaxUser];

int used=0;

//定义MFD目录中用已有的用户数

//文件管理

void fileCreate(char fileName[],int length,char fileKind[]);

//创建文件

void fileWrite(char fileName[]);

//写文件

void fileCat(char fileName[]);

//读文件

void fileRen(char fileName[],char rename[]);

//重命名文件

void fileFine(char fileName[]);

//查询文件

void fileDir(char UserName[]);

//显示某一用户的所有文件

void fileClose(char fileName[]);

//关闭已打开的文件

void fileDel(char fileName[]);

//删除文件

void chmod(char fileName[],char kind[]);

//修改文件的读写方式

int requestDist(int &startPostion,int maxLength); //磁盘分配查询

void initDisk();

//初始化磁盘

void freeDisk(int startPostion);

//磁盘空间释放

void diskShow();

//显示磁盘使用情况

//用户管理

void userCreate();

int login();

int userID=-1;

//用户登录的ID号,值为-1时表示没有用户登录

int main()

{

char order[commandAmount][10];

strcpy(order[0],\"create\");

strcpy(order[1],\"rm\");

strcpy(order[2],\"cat\");

strcpy(order[3],\"write\");

strcpy(order[4],\"fine\");

strcpy(order[5],\"chmod\");

strcpy(order[6],\"ren\");

strcpy(order[7],\"dir\");

strcpy(order[8],\"close\");

strcpy(order[9],\"return\");

strcpy(order[10],\"exit\");

strcpy(order[11],\"df\");

char command[50],command_str1[10],command_str2[10],command_str3[5],command_str4[3];

int i,k,j;

int length;

initDisk();

//初始化磁盘

for(i=0;i

//初始化用户UFD目录文件的头指针

{

userTable[i].user=(UFD *)malloc(sizeof(UFD));

userTable[i].user->next=NULL;

}

while(1)

{

printf(\"********************************************\\n\");

printf(\"

1、Creat user\\n\");

printf(\"

2、login\\n\");

printf(\"********************************************\\n\");

printf(\"Please chooce the function key:>\");

int choice;

scanf(\"%d\",&choice);

if(choice==1) userCreate();

else if(choice==2) userID=login();

else printf(\"您的输入有误,请重新选择\\n\");

while(userID!=-1)

{

fflush(stdin);

printf(\"———————————————————————————————————————\\n\");

printf(\" create-创建 格式:create a1 1000 rw,将创建名为a1,长度为1000字节可读可写的文件\\n\");

printf(\" rm-删除 格式:rm a1,将删除名为a1的文件\\n\");

printf(\" cat-查看文件内容 格式:cat a1,显示a1的内容\\n\");

printf(\" write-写入

格式:write a1\\n\");

printf(\" fine-查询 格式:fine a1 ,将显示文件 a1的属性\\n\");

printf(\" chmod-修改 格式:chmod a1 r,将文件a1的权限改为只读方式\\n\");

printf(\" ren-重命名 格式:ren a1 b1 ,将a1改名为b1\\n\");

printf(\" dir-显示文件 格式:dir aaa,将显示aaa用户的所有文件\\n\");

printf(\" df-显示磁盘空间使用情况 格式:df\\n\");

printf(\" close-关闭文件 格式:close a1,将关闭文件a1\\n\");

printf(\" return-退出用户,返回登录界面\\n\");

printf(\" exit-退出程序\\n\");

printf(\"————————————————————————————————————————\\n\");

printf(\"please imput your command:>\");

gets(command);

int select;

for(i=0;command[i]!=\' \'&&command[i]!=\'\\0\';i++)

//command_str1字符串存储命令的操作类型

command_str1[i]=command[i];

k=i;

command_str1[k]=\'\\0\';

for(i=0;i

{

if(!strcmp(command_str1,order[i]))

{

select=i;

break;

}

}

if(i==commandAmount)

{

printf(\"您输入的命令有误,请重新输入\\n\");

continue;

}

for(i=k+1,k=0;command[i]!=\' //commmand_str2字符串存储文件名或用户名

command_str2[k]=command[i];

command_str2[k]=\'\\0\';

k=i;

switch(select)

{

case 0:for(i=k+1,k=0;command[i]!=\' \';i++,k++)

command_str3[k]=command[i];

command_str3[k]=\'\\0\';

k=i;

j=1;

length=0;

//初始化文件长度

for(i=strlen(command_str3)-1;i>=0;i--)

//把字符串转换为十进制

{

length+=(command_str3[i]-48)*j;

j*=10;

}

\'&&command[i]!=\'\\0\';i++,k++)

for(i=k+1,k=0;command[i]!=\' \'&&command[i]!=\'\\0\';i++,k++)

command_str4[k]=command[i];

command_str4[k]=\'\\0\';

fileCreate(command_str2,length,command_str4);break;

case 1:fileDel(command_str2);break;

case 2:fileCat(command_str2);break;

case 3:

fileWrite(command_str2);break;

case 4:fileFine(command_str2);break;

case 5:for(i=k+1,k=0;command[i]!=\' \'&&command[i]!=\'\\0\';i++,k++)

command_str3[k]=command[i];

command_str3[k]=\'\\0\';

chmod(command_str2,command_str3);break;

case 6:for(i=k+1,k=0;command[i]!=\'\\0\';i++,k++)

command_str3[k]=command[i];

command_str3[k]=\'\\0\';

fileRen(command_str2,command_str3);break;

case 7:fileDir(command_str2);break;

case 8:fileClose(command_str2);break;

case 9:UFD *p;

for(p=userTable[userID].user->next;p!=NULL;p=p->next) //退出用户之前关闭所有打的文件

if(p->file->openFlag)

p->file->openFlag=false;

system(\"cls\");

userID=-1;break;

case 10:exit(0);break;

case 11:diskShow();break;

}

}

}

return 0;

}

void userCreate()

{

char c;

char userName[10];

int i;

if(used

{

printf(\"请输入用户名:\");

for(i=0;c=getch();i++)

{

if(c==13) break;

else

userName[i]=c;

printf(\"%c\",c);

}

userName[i]=\'\\0\';

for(i=0;i

{

if(!strcmp(userTable[i].userName,userName))

{

printf(\"\\n\");

printf(\"该用户名已存在,创建用户失败\\n\");

system(\"pause\");

return;

}

}

strcpy(userTable[used].userName,userName);

printf(\"\\n\");

printf(\"请输入密码:\");

for(i=0;c=getch();i++)

{

if(c==13) break;

else

userTable[used].paword[i]=c;

printf(\"*\");

}

userTable[userID].paword[i]=\'\\0\';

printf(\"\\n\");

printf(\"创建用户成功\\n\");

used++;

system(\"pause\");

}

else

{

printf(\"创建用户失败,用户已达到上限\\n\");

system(\"pause\");

}

fflush(stdin);

}

int login()

{

char name[10],psw[10];

char c;

int i,times;

printf(\"请输入用户名:\");

for(i=0;c=getch();i++)

{

if(c==13) break;

else

name[i]=c;

printf(\"%c\",c);

}

name[i]=\'\\0\';

for(i=0;i

{

if(!strcmp(userTable[i].userName,name))

break;

}

if(i==used)

{

printf(\"\\n您输入的用户名不存在\\n\");

system(\"pause\");

return -1;

}

for(times=0;times

{

memset(psw,\'\\0\',sizeof(psw));

printf(\"\\n请输入密码:\");

for(i=0;c=getch();i++)

{

if(c==13) break;

else

psw[i]=c;

printf(\"*\");

}

printf(\"\\n\");

for(i=0;i

{

if(!strcmp(psw,userTable[i].paword))

{

printf(\"用户登录成功\\n\");

system(\"pause\");

break;

}

}

if(i==used)

{

printf(\"您输入的密码错误,您还有%d次输入机会\\n\",2-times);

if(times==2) exit(0);

}

else break;

}

fflush(stdin);

return i;

}

void initDisk()

{

diskHead=(diskNode *)malloc(sizeof(diskNode));

diskHead->maxlength=MaxDisk;

diskHead->useFlag=0;

diskHead->start=0;

diskHead->next=NULL;

}

int requestDist(int &startPostion,int maxLength)

{

int flag=0; //标记是否分配成功

diskNode *p,*q,*temp;

p=diskHead;

while(p)

{

if(p->useFlag==0&&p->maxlength>maxLength)

{

startPostion=p->start;

q=(diskNode *)malloc(sizeof(diskNode));

q->start=p->start;

q->maxlength=maxLength;

q->useFlag=1;

q->next=NULL;

diskHead->start=p->start+maxLength;

diskHead->maxlength=p->maxlength-maxLength;

flag=1;

temp=p;

if(diskHead->next==NULL) diskHead->next=q;

else

{

while(temp->next) temp=temp->next;

temp->next=q;

}

break;

}

p=p->next;

}

return flag;

}

void fileCreate(char fileName[],int length,char fileKind[])

{

//int i,j;

time_t rawtime;

int startPos;

UFD *fileNode,*p;

for(p=userTable[userID].user->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

{

printf(\"文件重名,创建文件失败\\n\");

system(\"pause\");

return;

}

}

if(requestDist(startPos,length))

{

fileNode=(UFD *)malloc(sizeof(UFD));

fileNode->file=(fileTable *)malloc(sizeof(fileTable)); //这一步必不可少,fileNode里面的指针也需要申请地址,否则fileNode->file指向会出错

strcpy(fileNode->file->fileName,fileName);

strcpy(fileNode->file->fileKind,fileKind);

fileNode->file->maxlength=length;

fileNode->file->strat=startPos;

fileNode->file->openFlag=false;

time(&rawtime);

fileNode->file->timeinfo=localtime(&rawtime);

fileNode->next=NULL;

if(userTable[userID].user->next==NULL)

userTable[userID].user->next=fileNode;

else

{

p=userTable[userID].user->next;

while(p->next) p=p->next;

p->next=fileNode;

}

printf(\"创建文件成功\\n\");

system(\"pause\");

}

为因

else

{

printf(\"磁盘空间已满或所创建文件超出磁盘空闲容量,磁盘空间分配失败\\n\");

system(\"pause\");

}

}

void freeDisk(int startPostion)

{

diskNode *p;

for(p=diskHead;p!=NULL;p=p->next)

{

if(p->start==startPostion)

break;

}

p->useFlag=false;

}

void fileDel(char fileName[])

{

UFD *p,*q,*temp;

q=userTable[userID].user;

p=q->next;

while(p)

{

if(!strcmp(p->file->fileName,fileName)) break;

else

{

p=p->next;

q=q->next;

}

}

if(p)

{

if(p->file->openFlag!=true)

//先判断是否有进程打开该文件

{

temp=p;

q->next=p->next;

freeDisk(temp->file->strat); //磁盘空间回收

free(temp);

printf(\"文件删除成功\\n\");

system(\"pause\");

}

else

{

printf(\"该文件已被进程打开,删除失败\\n\");

system(\"pause\");

}

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void fileCat(char fileName[])

{

int startPos,length;

int k=0;

UFD *p,*q;

q=userTable[userID].user;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

startPos=p->file->strat;

length=p->file->length;

p->file->openFlag=true;

//文件打开标记

printf(\"*****************************************************\\n\");

for(int i=startPos;k

{

if(i%50==0) printf(\"\\n\"); //一行大于50个字符换行

printf(\"%c\",disk[i]);

}

printf(\"\\n\\n*****************************************************\\n\");

printf(\"%s已被read进程打开,请用close命令将其关闭\\n\",p->file->fileName);

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void fileWrite(char fileName[])

{

UFD *p,*q;

q=userTable[userID].user;

int i,k,startPos;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

if(!strcmp(p->file->fileKind,\"r\"))

//判断文件类型

{

printf(\"该文件是只读文件,写入失败\\n\");

system(\"pause\");

return;

}

char str[500];

printf(\"please input content:\\n\");

gets(str);

startPos=p->file->strat;

p->file->openFlag=true;

//文件打开标记

p->file->length=strlen(str);

if(p->file->length>p->file->maxlength)

{

printf(\"写入字符串长度大于该文件的总长度,写入失败\\n\");

system(\"pause\");

return;

}

for(i=startPos,k=0;k

disk[i]=str[k];

printf(\"文件写入成功,请用close命令将该文件关闭\\n\");

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void fileFine(char fileName[])

{

UFD *p,*q;

q=userTable[userID].user;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

printf(\"********************************************\\n\");

printf(\"文件名:%s\\n\",p->file->fileName);

printf(\"文件长度:%d\\n\",p->file->maxlength);

printf(\"文件在存储空间的起始地址:%d\\n\",p->file->strat);

printf(\"文件类型:%s\\n\",p->file->fileKind);

printf(\"创建时间:%s\\n\",asctime(p->file->timeinfo));

printf(\"********************************************\\n\");

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void chmod(char fileName[],char kind[])

{

UFD *p,*q;

q=userTable[userID].user;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

strcpy(p->file->fileKind,kind);

printf(\"修改文件类型成功\\n\");

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void fileRen(char fileName[],char name[])

{

UFD *p,*q;

q=userTable[userID].user;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

while(q->next)

{

if(!strcmp(q->next->file->fileName,name))

{

printf(\"您输入的文件名已存在,重命名失败\\n\");

system(\"pause\");

return;

}

q=q->next;

}

strcpy(p->file->fileName,name);

printf(\"重命名成功\\n\");

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

void fileDir(char userName[])

{

UFD *p;

int i,k;

for(i=0;i

{

if(!strcmp(userTable[i].userName,userName))

{

k=i;break;

}

}

if(i==MaxUser)

{

printf(\"没有找到该用户,请检查输入用户名是否正确\\n\");

system(\"pause\");

return;

}

else

{

p=userTable[k].user->next;

printf(\"********************************************************************************\\n\");

printf(\"文件名

文件长度

文件在磁盘的起始地址

文件类型

创建时间\\n\");

for(;p!=NULL;p=p->next)

printf(\"%s

%d

%d

%s

%s\",p->file->fileName,

p->file->maxlength,p->file->strat,p->file->fileKind,asctime(p->file->timeinfo));

printf(\"********************************************************************************\\n\");

system(\"pause\");

}

}

void diskShow()

{

diskNode *p;

int i=0,unusedDisk=0;

printf(\"***************************************************************************\\n\");

printf(\" 盘块号

起始地址

容量(bit)

是否已被使用\\n\");

for(p=diskHead;p!=NULL;p=p->next,i++)

{

if(p->useFlag==false) unusedDisk+=p->maxlength;

printf(\"

%d

%d

%d

%d

\\n\",i,p->start,p->maxlength,p->useFlag);

}

printf(\"***************************************************************************\\n\");

printf(\"磁盘空间总容量:512*1024bit 已使用:%dbit

末使用:%dbit\\n\\n\",MaxDisk-unusedDisk,

unusedDisk);

system(\"pause\");

}

void fileClose(char fileName[])

{

UFD *p,*q;

q=userTable[userID].user;

for(p=q->next;p!=NULL;p=p->next)

{

if(!strcmp(p->file->fileName,fileName))

break;

}

if(p)

{

p->file->openFlag=false;

printf(\"%s文件已关闭\\n\",p->file->fileName);

system(\"pause\");

}

else

{

printf(\"没有找到该文件,请检查输入的文件名是否正确\\n\");

system(\"pause\");

}

}

运行结果视图:

(略)

推荐第10篇:操作系统课程设计教学大纲

操作系统课程设计大纲

课程名称:操作系统课程设计 课程编码:10110206 英文名称:Course Design of Operating System 学 时: 二周 学 分:2

适用专业:计算机科学与技术、计算机网络工程、计算机软件工程 课程类别:必修

课程性质:学科基础课 先修课程:C++程序设计,数据结构,计算机组成原理 参考教材:

计算机操作系统教程,清华大学出版社,张尧学等,2006.10 现代操作系统,机械工业出版社,陈向群等译,2005.9

一、课程性质与任务

“操作系统基础”是计算机专业的核心专业课,“操作系统课程设计”是理解和巩固操作系统基本理论、原理和方法的重要的实践环节。

操作系统课程主要讲述的内容是计算机操作系统的基本原理及组成,操作系统中常用的设计技巧和方法。它与计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法;在算法基础上,解决实际问题,提高学生实际应用、编程的能力。

二、课程教学的基本要求

学生针对操作系统课程设计题目所提出的问题,查阅相关资料,利用操作系统中的基本原理和方法,通过分析、设计、编码、调试,实现完整的解决方案。

三、课程设计题目及要求

题目:Linux二级文件系统设计

要求:系统采用两级目录,其中第一级对应于用户账号,第二级对应于用户帐号下的文件;使用内存来模拟外存,进行数据结构设计和操作算法的设计,实现一个文件系统并实现基本的文件操作。

四、课程学时分配

总设计时间:两周

五、课程设计内容与安排

1、问题分析及解决方案确定;

2、形成编程思路;

3、使用具体语言实现算法;

4、上机调试程序;

5、编写课程设计报告.

六、考核方式

考核的内容包括:程序语言描述的科学性、系统性,程序设计的正确性,程序设计文档的系统性可读性,学生的工作态度、动手能力、是否有创新,总结报告的质量。

课程设计结束时,要求学生按照统一格式写出课程设计报告。

以编写的程序和学生实际操作能力为主,参考提问和出勤情况等,综合评定给出成绩。

七、课程的主要参考书

1.现代操作系统,机械工业出版社,陈向群 等译, 2005 2.操作系统原理·技术与编程,机械工业出版社,蒋 静等编著, 2004 3.计算机操作系统,西安电子科技大学出版社,方敏主编,2004.8 4.计算机操作系统(第二版),西安电子科技大学出版社,汤子灜等编著, 2001 5.操作系统实验指导,清华大学出版社,任爱华等 编著, 2004

制定人: 任德华

审定:

批准:

第11篇:操作系统课程设计报告

课程设计报告

题 目: 模拟请求页式管理

课程名称: 计算机操作系统 学 院: 信息工程学院

专 业: 计算机科学与技术

班 级: 14计本(1) 学生姓名: * * * 学 号: 201403031** 指导教师: * * 成 绩:

开课时间: 2016-2017 学年 一 学期

模拟请求页式管理

第1章 需求分析

1.1设计要求

请求页式管理是一种常用的虚拟存储管理技术。本设计通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。本实验要求用Vc++或其他高级语言编写和调试。

编写程序实现:

(1)先进先出页面置换算法(FIFO) (2)最近最久未使用页面置换算法(LRU) 最佳置换页面置换算法(OPT) 设计一个虚拟存储区和内存工作区,编程序演示以上三种算法的具体实现过程,并计算访问命中率。

1.2解决方案

首先确定实现语言使用c#实现图形化界面,后确定要实现哪些功能,比如算法选择,页面添加,模拟控制。然后确定输出结构以便于程序的测试和验证。将基本框架建立后再进行编程。编程前进行算法结构分析最后编程实现。

1.3算法实现原理

1、先进先出置换算法(FIFO):

发生缺页中断时按照页面进入内存顺序总是淘汰最先进入内存的页面。

2、最近最久未使用置换算法(LRU):

发生缺页中断时总是淘汰存在内存中最长时间未被使用的页面。

3、最佳置换算法(OPT):

发生缺页中断时若一个或几个页面将来将不会被调用则按先进先出原则淘汰页面,若将来都有调用则比较调用时刻选择最远时刻页面淘汰。

4、缺页率:缺页次数占页面调用次数的百分比。

第2章 概要设计

2.1数据设计

常变量:调用页面最大数量(MaxN),内存最大页面数(MaxM) 待调用页面数组:page_dd[MaxN]存放等待调用的页面号

页面数组专用指针 page_p,用于指向page_dd数组中正需调入内存的页号 内存块数组:Memery[MaxM],存放内存当前存放的页号 缺页计数器:count,记录缺页次数

内存块状态数组:M1[MaxN],M2[MaxN],M3[MaxN],记录每次页面调用结束后内存各块的状态

缺页记录数组s[MaxN],用于记录页面调用时是否产生缺页中断,初始化为是

2.2函数设计

1、页面添加函数:void btnAdd_Click(object sender, EventArgs e) 用于实现通过点击按钮实现数据输入。

2、内存初始化函数:init(int[] a, int[] b,int []m1,int[]m2,int[]m3) 参数有页面数组、内存数组、状态数组,采用先进先出算法对内存先进行装满 服务于先进先出页面置换函数和最佳置换函数。

3、输出函数:void display(int[]a,int[]m1,int[]m2,int[]m3,char[]c)用于输出模拟结果,参数有页面数组,内存数组,状态数组,缺页记录数组。再模拟之后调用。

4、模拟控制函数:void btnmo_Click(object sender, EventArgs e)用于实现通过单击模拟按钮,根据用户所选算法进行模拟并显示结果。

5、先进先出算法模拟函数:

void FIFO(int[] a, int[] b,int[]m1,int[]m2,int[]m3,char[] s)用于实现先进先出算法模拟,参数有页面数组,内存数组、内存状态记录数组,缺页记录数组。在模拟函数中调用。

6、最近最久未使用算法模拟函数:

void LRU(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s)用于 3 实现最近最久未使用算法模拟,参数有页面数组,内存数组,内存状态记录数组,缺页记录数组。在模拟函数中被调用。

7、最近最久未使用函数辅助函数:void LUR_I(int[] a,int e)用于对最近最久未使用算法中所用辅助数组(记录页面存在时长)进行调整,参数有辅助数组及需调整的数据下标。在最近最久未使用函数中调用。

8、最佳置换算法模拟函数:

void OPT(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s)用于模拟最佳置换算法。参数有页面数组,内存数组,内存状态记录数组,缺页记录数组。在模拟函数中被调用。

9、最佳置换算法辅助函数:void OPT_F(int[] a, int e)用于对最佳置换算法中的辅助数组进行调整。参数有辅助数组,需调整数据下标。在最佳置换算法中被调用。

10、重置函数:void btncz_Click(object sender, EventArgs e)用于重新选择算法进行新的模拟。

2.3主要算法设计

1、初始化函数算法:

第一步:将第一个页面调入内存,调整最佳置换算法辅助数组,缺页计数器加一,保存内存数组状态。

第二步:调用下一个页面并判断内存中是否有本页面有转第三步,无转第四步。 第三步:更改缺页数组对应下标值,记录当前内存状态,调整最佳置换算法辅助数组,页面指针指向下一页。

第四步:将页面调入内存,调整最佳置换算法辅助函数,缺页计数器加一,保存内存数组状态。若内存尚不满转第一步。 具体见图1初始化算法流程图。

开始页面调入内存缺页计数器加一记录内存状态调用下一页否否内存是否有该页面是记录内存状态修改缺页数组内存已满是结束

图1 初始化算法流程图

2、先进先出页面置换算法:

第一步:检查内存中是否已有需调用页面,有则转第二步,无则转第三步。 第二步:记录当前内存状态,修改缺页数组对应下标值。

第三步:内存中无需要调用的页面,进行出队操作,然后进行入队操作,记录内存块状态,缺页计数器加一。

第四步:若页面数组未被调用结束转第一步。 具体见图2先进先出算法流程图。

开始页面调入内存该页在内存中是否已存在是否否先出队操作后入队操作记录内存状态修改缺页数组值记录内存状态缺页计数器加一页面调用结束是结束

图2 先进先出算法流程图

3、最近最久未使用置换算法:

第一步:将页面调入内存,记录内存状态,缺页计数器加一,调整辅助数组,页面指针加一。

第二步:检查内存中是否已有所需页面,有转第三步,无转第一步。

第三步:修改缺页数组对应下标记录,记录内存状态,调整辅助数组,页面指针加一。

6 第四步:内存是否已满,无则转第一步,是则转第五步。

第五步:检查内存中是否有所需页面,有则记录当前内存状态,修改缺页数组对应下标值。无则转第六步。

第六步:检查辅助数组找出最大值并记录其下标,置换内存中对应下标的数据,调整辅助数组,缺页计数器加一。

第七步:页面是否调用结束未结束则转第五步。 具体见图3最近最久未使用算法流程图。

开始调入页面至内存记录内存状态计数器加一否调整辅助数组调用下一页内存中是否已有该页否内存已满是通过辅助数组确定淘汰页面是修改缺页数组记录内存状态调整辅助数组否页面置换记录内存状态计数器加一调用结束是结束

图3 最近最久未使用算法

4、最佳置换算法:

第一步:检查内存中是否已有所需页面,有则记录内存状态,修改缺页数组对应下标数值。无则转第二步。

第二步:判断内存中各页面的未来调用情况,记录是否还有调用,若有则记录调用时刻。

第三步:分析调用情况,内存中页面都在将来不会被调用转第四步,有一个被调用转第五步,有两个被调用转第六步,全被调用转第七步。

第四步:查找辅助数组找到内存中存在时间最长的页面进行置换,修改内存状态,缺页计数器加一,修改辅助数组。

第五步:查找到不会被调用的页面,并根据辅助数组选择最早进入内存的页面将其置换。修改内存状态,缺页计数器加一,修改辅助数组。

第六步:查找辅助数组找到将来不需要在调用的页面将其置换,修改辅助数组,记录内存状态,缺页计数器加一。

第七步:查找辅助数组,找寻最晚被调用的页面,将其置换。记录内存状态,修改辅助数组,缺页计数器加一。

第八步:页面是否调用完成,否则转第一步。 具体见图4最佳置换算法流程图

开始调入页面记录内存状态计数器加一更新辅助函数是页面已存在否向后检查内存当前页面调用情况所有页面都不会再度调用否是一个页面会调用否否是两个页面会调用是否查找辅助数组得到最先进入页面通过辅助数组得到不会再调用的页面通过辅助数组获取最晚调用的页面通过辅助数组得到另外两个页面中最先进入的页面置换页面记录内存状态计数器加一更新辅助函数页面调用结束是结束

图4 最佳置换算法流程图

10 2.4界面设计

采用c# 设计windows窗体应用程序,使用下拉列表框选择算法,通过按钮添加待调用的页面。通过文本控件显示模拟结果。 显示样式:第一行:算法名称;

第二行:调用页面顺序;

第三行至第五行显示内存在每调用一次页面后的状态;

第六行:是否缺页;

最后一行显示缺页率;

第3章 详细设计与实现

3.1函数设计

1、添加按钮功能实现代码

主要功能:实现单击一次添加一个调用页面,并给出相应的提示,如正在输入的是第几次调度页面,在输入为空时能够弹出对话框提示用户,在输入完成时为避免数组越界应在输入完成时隐藏;输入过程中始终保证时输入焦点。 private void btnAdd_Click(object sender, EventArgs e) { if (txtAdd.Text != \"\")//输入不为空才能继续输入 { page_dd[i_add] = Convert.ToInt32(txtAdd.Text); /*将输入值赋值给页面数组*/ txtShow.Text += txtAdd.Text + \" \"; /*显示供用户查阅*/ i_add++; txtAdd.Clear(); /*清空*/ if (i_add == MaxN)//输入结束时 { txtAdd.ReadOnly = true;//不允许继续输入 btnAdd.Hide();//按钮隐藏 return; } txtAdd.Focus();//设置为输入焦点

label2.Text = \"第\" + (i_add + 1) + \"次调度页面:\"; /*提示用户正在输入的是第几次调度页面*/ } /*输入为空则弹出对话框提示用户输入为空*/

12 else { MeageBox.Show(\"请输入调用页面!\", \"输入为空\", MeageBoxButtons.OK, MeageBoxIcon.Warning); txtAdd.Focus(); } }

2、初始化函数

主要功能:将内存一先进先出方式填满,并记录每个页面进入时间,服务于先进先出页面置换算法和最佳置换算法。

void init(int[] a, int[] b,int []m1,int[]m2,int[]m3) { /*内存未满时循环*/ for (int i = 0; i

//调整辅助数组将刚进入内存的页面的对应时间 OPT_F (O_Q ,i); count++;//缺页计数器加一 m1[page_p] = b[0];//保存内存状态 m2[page_p] = b[1]; m3[page_p] = b[2]; page_p++;//调用下一页面

//检查内存中是否原先就有需要的页面; for (int j = 0; j

13 s[page_p] = \'F\';//缺页数组对应数据更改 m1[page_p] = b[0];//记录内存状态 m2[page_p] = b[1]; m3[page_p] = b[2]; OPT_F(O_Q, -1);//调整最佳置换算法辅助函数 page_p++;//调用下一页 j = -1;//重新开始寻找 } } } }

3、先进先出页面置换函数

主要功能:根据先进先出算法要求在产生缺页中断时采用先进先出方式确定淘汰页面,并在每次页面调用时记录下内存状态,缺页次数;采用循环队列使得每次出队的一定是最先进入内存的。

private void FIFO(int[] a, int[] b,int[]m1,int[]m2,int[]m3,char[] s) { int Fpage_p = page_p; int front, rear; //定义队列对手和对尾指针并初始化 front = 0; rear = MaxM1; int sa; for (; Fpage_p

{ if (b[i] == a[Fpage_p]) { m1[Fpage_p] = b[0]; m2[Fpage_p] = b[1]; m3[Fpage_p] = b[2]; s[Fpage_p] = \'F\'; sa = 1; break; } } if (sa == 0) { front = (front + 1) % MaxM;

38 rear = (rear + 1) % MaxM; b[rear] = a[Fpage_p]; m1[Fpage_p] = b[0]; m2[Fpage_p] = b[1]; m3[Fpage_p] = b[2]; count++; } else continue; } } /*最近最久未使用算法辅助数组调整函数*/ private void LUR_I(int[] a,int e) { int temp; temp = a[e]; a[e] = 1; for (int i = 0; i

39 int[] L_Q = new int[MaxM]{3,3,3}; int sa; for (int i = 0; i

检查内存中是否已有要调40 for (int i = 0; i

{

if (b[i] == a[page_p]) { m1[page_p] = b[0]; m2[page_p] = b[1]; m3[page_p] = b[2]; OPT_F(O_Q,-1);

41 s[page_p] = \'F\'; sa = 1; break; } } if (sa == 0)//缺页 { Ocount = 0; for (int i = 0; i O_Q[temp]) temp = i; } b[temp] = a[page_p]; m1[page_p] = b[0]; m2[page_p] = b[1]; m3[page_p] = b[2]; OPT_F (O_Q ,temp); count++; break; case 1://有一个页面将在以后调用 temp = 0; for (int i = 0; i O_Q[temp]) temp = i;

42 } b[temp] = a[page_p]; m1[page_p] = b[0]; m2[page_p] = b[1]; m3[page_p] = b[2]; OPT_F (O_Q ,temp); count++; break; case 2: for (int i = 0; i OPT_J[p]) p = i; } b[p] = a[page_p]; m1[page_p] = b[0]; m2[page_p] = b[1]; m3[page_p] = b[2]; OPT_F(O_Q, p); count++; break; } } } } /*重置函数*/ private void btncz_Click(object sender, EventArgs e) { comboBox1.SelectedIndex = 0;

43 txtAdd.Text = \"\"; page_p = 0; i_add = 0; count = 0; //txtShow.Text = \"\"; for (int i = 0; i

44

第12篇:操作系统课程设计报告

操 作 系 统

学院:计算机科学与技术学院

班级:计112

学号:1113022032

姓名:

一、实验名称:

用C++实现驱动调度算法、页面替换算法、银行家算法、处理器调度算法

二、实验要求:

书写实验报告,包括的内容有:

(1) 实验题目

(2) 程序中使用的数据结构及主要文字说明

(3) 带有注释的源程序

(4) 执行程序说明,表明各进程控制快的初始状态,以及各算法的运行状态

(5) 通过实验后的收获与体会及对实验的改进意见和见解

二、实验目的:

通过自己编程来实现各类操作系统算法,进一步理解操作系统的概念及含义,提高对操作系统的认识,同时提高自己的动手实践能力。加强我们对各类算法的理解。

三、实验内容:

1、实现页面替换算法

(1)FIFO 先进先出页面替换算法

(2)LRU最近最少使用页面替换算法

(3)LFU最少使用频率页面替换算法

2、银行家算法

3、实现驱动调度算法

(1)先来先服务算法

(2)电梯算法

(3)扫描算法

4、实现处理器调度

(1) 先进先出处理器调度

(2) 时间片轮转法

(3) 优先级调度

四、实验原理:

1、页面替换算法

先进先出页面置换算法:该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面加以淘汰。将已调入内存的页面按先后次序链接成一个队列,将最先调入的页面与新页面进行置换

最近最久未使用置换算法:该算法是利用“最近的过去”作为“最近的将来”,将最近最久未使用的页面加以淘汰。将已调入内存的页面按先后顺序链接成一个队列,为每一个页面增加一个访问字段,用来记录一个页面自上次被访问以来所经历的是时间t,当需淘汰一个页面时,选择现有页面中其t值最大,即最近最久未使用的页面加以淘汰

2、银行家算法

先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。若请求合法,则进行试分配。最后对试分配后的状态调用安全性检查算法进行安全性检查。若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。

3、驱动调度算法

先进先出算法(FIFO):总是严格按时间顺序对磁盘请求予以处理。算法实现简单、易于理解并且相对公平,不会发生进程饿死现象。但该算法可能会移动的柱面数较多并且会

经常更换移动方向,效率有待提高

电梯调度算法:总是将一个方向上的请求全部处理完后,才改变方向继续处理其他请求。

扫描算法(scan algorithm):总是从最外向最内(或最内向最外)进行扫描,然后在从最内向最外(或最外向最内)扫描。该算法与电梯调度算法的区别是电梯调度在没有最外或最内的请求时不会移动到最外或最内柱面。

4、处理器调度算法

先进先出处理器调度:按照作业进入系统后备工作队列的先后次序来挑选作业,

先进入系统的作业将优先被挑选进入主存,创建用户进程,分配所需资源,然后移入就绪队列。

时间片轮转法调度算法:调度次序每次把CPU分配给就绪队列进程/线程使用规

定的时间间隔,就绪队列中每个进程/线程轮流的运行一个时间片,当时间片耗尽时,就强迫当前运行进程/线程让出处理器,转而排列到就绪队列尾部,等候下一轮调度。

优先级调度:根据确定的优先级来选取进程/线程,总是选择就绪队列中的优先

级最高者投入运行,即优先级越高,先被调用。

五、数据结构设计

对操作系统的各类算法设计数据结构如下:

页面替换算法:void FIFO();void LRU();void LFU();

银行家算法:void Init() 初始化算法

void Bank() 银行家算法

bool Safe() 安全性算法

驱动调度算法:

struct MagneticHead//磁头构成

{

int site;

int count;

bool direct;

};

struct Range//磁盘磁道范围

{

int mStart;

int mEnd;

};

struct RequestList//请求序列

{

int site;

bool state;

};

struct Data//基本数据集合

{

MagneticHead magneticHead;

RequestList *requestList;

int *executeList;

Range range;

int length;

};

处理器调度:

typedef struct pcb//时间片轮转法

{

char pname[N];

int runtime;

int arrivetime;

char state;

struct pcb*next;

}PCB;

typedef struct PCB1//先进先出服务

{

char ID[3];//进程号

char name[10];//进程名

char state;//运行状态

floatarrivetime;//到达时间

floatstarttime;//进程开始时间

floatfinishtime;//进程结束时间

floatservicetime;//服务时间

float turnaroundtime;//周转时间

float weightedturnaroundtime;//带权周转时间

struct PCB1 *next;//指向下个进程

}pcb1;

struct pcb2 {优先级调度

char name[10];

char state;

int super;

int ntime;

int rtime;

struct pcb2* link;

}*ready=NULL,*d;

typedef struct pcb2 PCB2;

六、课程设计总结

在本次课程设计中,就是讲平时所做的实验结合起来,实现操作系统的各类算法,了解操作系统的运行原理以及其基本概念,更好的将操作系统的原理很好的展现出来。同时,在本次实验中遇到了很多问题,需要我们仔细的检查和修改。其次,实验中为了能更好的体现各类算法的运行情况,需要做一个清晰的界面,以能清楚地看出运行结果。

第13篇:操作系统课程设计(补考)

课程设计(补试)

设计1

编写一组小程序测试你的Windows 2K/XP系统创建进程和线程的能力。 提示: 考察你的系统能够创建的进程和线程数目的极限,进程和线程启动后可以进入睡眠状态或者死循环,对结果有何影响?考虑CreateThread等函数不同参数的意义,数据收集应该考虑不同的系统负荷。

报告要求: 说明你的程序运行的系统资源配置 给出测试结果,结果应能反映前面提到的情况 对测试程序和结果做出说明 结合你的结果回答如下问题: Windows 2k/xp中进程和线程在表现上有什么差别? 是什么原因导致对进程和线程测试结果的差异? 你认为哪些因素影响系统维持多进程/多线程的能力,体现在哪些方面?

设计2

测试Windows 2k中内存和外存的速度。 分别在内存中分配一片存储空间,和在硬盘上建立一个同样大小的空间,往这两个空间中用不同方式写入/读出数据。根据分配大小的不同,比较两者的速度差异,并对你所观测到的现象进行分析和解释。

报告要求: 描述测试性能曲线; 对你得到的性能进行解释,并分析影响硬盘速度的因素;对Windows 2k的虚存管理进行分析。

设计3

列举生活中发生的一种同步或互斥的现象(如生产者消费者),并使用Windows 2k中的线程和信号灯互斥量等编程描述这一现象。

报告要求: 陈述你所要描述的现象以及如何对该现象进行抽象的方法;

第14篇:操作系统课程设计教学大纲

《操作系统课程设计》教学大纲

一、课程设计基本信息 课程设计环节代码:230027 课程设计环节名称:操作系统课程设计

英文名称:Course Design of Operating System 课程设计周数:2周 学分:2.0 适用对象:计算机科学与技术专业、网络工程专业

先修课程与环节:高级语言程序设计、数据结构和操作系统

二、课程设计目的和任务

本课程是计算机专业的学生在学习了《操作系统》课程之后,为了加深和巩固学生对所学操作系统各个理论和算法知识的理解,同时提高学生利用操作系统知识综合运用的能力和分析问题、解决的问题的能力而开设的一门实践课程。

通过本环节学生能够充分把学到的知识应用到实际的编程实践中,有可以进一步巩固操作系统中学习的理论。通过算法实现各种控制应用进一步体会操作系统中基本功能模块的结构和实现方法的实质,建立深入了解现有操作系统的评价和比较的方法,加深体会利用操作系统的原理能够解决实际问题的在计算机系统编程和普通编程中解决实际问题的思路;通过对程序编写规范,可以培养学生良好的编程风格,包括程序结构形式,行文格式和程序正文格式等;并培养学生的上机调试能力。

三、课程设计方式

1、课程设计题目的选定

采用指导教师提供参考题目与学生自主命题相结合的办法选定课程设计题目。一人一题,不得重复。其中学生自主命题需要指导教师严格的审核,看是否满足课程要求,检查是否为重复课题。

2、课程设计任务的完成

在指导教师的指导下,各个学生独立完成课题分析、设计、代码编写和调试,独立撰写课程设计报告。所有工作任务主要在微机实验室完成。

四、课程设计教学方法与要求

课程设计教学方法:主要以学生上机操作为主,教师指导为辅 课程设计要求:

1、对系统进行功能分解、模块分析、控制模块分析正确

2、选择合适的操作系统原理所需要数据结构以及相应的算法

3、程序规模适中,着重于内核修订功能,也可以编写外围的程序驱动、文件系统的辅助工具和网络工具等。尽可能的使系统的功能更加完善和全面

4、掌握程序调试的方法

5、说明书、流程图要清楚,阐明设计思路。

6、撰写课程设计报告。按格式要求写出完整、规范的报告并打印。其中模块图、流程图要清楚、规范。特别要求学生自己独立完成。

五、课程设计内容和时间安排

(一)动员、准备及规划(1天)

实习具体内容:动员、选题、系统功能和需求的分析 时间分配:上午动员、下午选题及规划 实习地点:机房

(二)课程设计实施、检查(1天)

实习具体内容:需求分析说明书和任务规划,设计出每个功能 时间分配: 上午上机、下午初期检查 实习地点: 机房

(三)课程设计实施(12天)

实习具体内容: 具体功能的实现及系统的完善工作、中期检查 时间分配: 11.5天上机,0.5天中期检查 实习地点: 机房

(四)整理报告(1天)

实习具体内容: 文档整理、设计报告的完成 时间分配: 全部时间写报告 实习地点:机房或图书馆

六、课程设计基本要求

(一)动员、准备及规划

1、要求:通过学习,使学生了解所选择开发环境的程序运行环境中的调试功能,掌握跟踪、修改错误的技巧。

2、重点:题目的选定和结合操作系统原理的各个部分确定实现的功能以及和原理的结合,难点:对于程序运行环境学会断点设置以及中间结果的检查。

3、说明:题目自选也可以参考教师提供的题目,选题要紧密结合课堂教学内容;并建立一个可行的工作计划;熟悉程序运行环境。

(二)课程设计实施、检查

1、要求:领会按照实际的结构,使学生能根据实际问题选择数据结构,清晰的描述算法

2、重点和难点:算法分析和设计

3、说明:学生自检和指导教师检查相结合,严格按照拟订计划完成任务

(三)课程设计实施

1、要求:培养良好的编程风格,掌握所选编程语言

2、重点和难点:算法分析和设计

3、说明:学生自检和指导教师检查相结合,严格按照拟订计划完成任务

(四)整理报告

1、要求:通过学习,使学生掌握报告书写规范

2、重点:格式的规范

3、说明:指导教师检查

七、课程设计的考核方式和成绩评定标准

(一)课程设计考核方式

点名、各个环节的考核及程序检查、设计报告的综合评定。

(二)课程设计成绩评定标准 课程设计成绩=点名*10%+程序检查*30%+设计报告*60% 由指导教师根据学生完成任务的情况、课程设计报告的质量和课程设计过程中的工作态度等综合打分。成绩评定实行优、良、中、及格和不及格五个等级。不及格者不能得到相应的学分,需重新做课程设计,经指导教师考核及格后,方可取得相应学分。

优:有完整的符合标准的文档,文档有条理、文笔通顺,格式正确,其中有总体设计思想的论述;程序完全实现设计方案,设计方案先进,软件可靠性好;

良:有完整的符合标准的文档,文档有条理、文笔通顺,格式正确;有完全实现设计方案的软件,设计方案较先进;

中:有完整的符合标准的文档,有基本实现设计方案的软件,设计方案正确;

及格:有完整的符合标准的文档,有基本实现设计方案的软件,设计方案基本正确; 不及格:没有完整符合标准的文档,软件没有基本实现设计方案,设计方案不正确。 提交的电子文档和软件必须是由学生自己独立完成,雷同者教师有权视其情况扣分或记零分。

八、课程设计指导书 孙钟秀编《操作系统教程》(高等教育出版社)

九、其他说明

(一)课程设计报告要求:

总结报告按如下内容顺序用A4纸进行撰写并打印装订成册:

1、统一的封面;

2、内容摘要;

3、目录;

4、课程设计正文包含以下内容: (1)需求分析

(2)概要设计:每个部分的算法设计说明可以是描述算法的流程图,说明每个程序中使用的存储结构设计(如果指定存储结构请写出该存储结构的定义)。

(3)详细设计:各个算法实现的源程序,源程序要按照写程序的规则来编写。要结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。 (4)调试分析:测试数据,测试输出的结果,算法时间复杂度分析 E结论和展望:每个模块设计和调试时存在问题的思考(问题是哪些?问题如何解决?),和算法的改进设想。课程设计过程的收获、遇到问题解决问题过程的思考、程序调试能力的思考、对数据结构这门课程的思考、在课程设计过程中对《数据结构》课程的认识等内容。

(5)按统一格式列出主要参考文献。

(二)学生上交材料:

1、程序源代码和一组较完备的测试数据(打包上传,发送到各个指导老师的邮箱中,文件名格式为“姓名-班级-学号” );

2、上交程序的说明文件:(保存在.txt中)在说明文档中应该写明上交程序所在的目录,上交程序的主程序文件名,如果需要安装,要有程序的安装使用说明;

3、课程设计报告

大纲修订人:闫大顺 修订日期:2006年8月20 大纲审定人: 审定日期: 附:指导教师推荐题目(供参考) 选题:题目大小适中

课题

一、编制银行家算法通用程序,并检测所给状态的系统安全性。

设计目的:主要是解决多种资源的被多个独立执行的程序使用的安全算法。银行家算法就是采用矩阵存储资源的数据进行处理的方法。 设计的要求:

1)资源的种类和数目可以变化的 2)进程可以的任意的顺序创建和变化 3)采用保守的方法来分配资源。

课题

二、处理机调度程序:选择一个调度算法,实现处理机调度。

设计目的:在多道程序和多任务系统中,系统内同时处于就绪状态的进程可能有若干个。也就是说能运行的进程数大于处理机个数。为了使系统中的进程能有条不紊地工作,必须选用某种调度策略,选择一进程占用处理机。要求学生设计一个模拟处理机调度算法,以巩固和加深处理机调度的概念。 设计要求:

1)进程调度算法包括:时间片轮转法,短作业优先算法,动态优先级算法。 2)可选择进程数量

3)本程序包括三种算法,用C语言实现,执行时在主界面选择算法(可用函数实现),进入子页面后输入进程数,(运行时间,优先数由随机函数产生),执行,显示结果。

课题

三、用多进程同步方法解决生产者-消费者问题

设计目的:通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制.说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数.设计要求: 1) 每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者县城的标识符.2) 生产者和消费者各有两个以上.3) 多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码.

课题

四、设计虚拟存储区和内存工作区,编程序演示下述算法的具体实现过程,并计算访问命中率: 要求设计主界面以灵活选择某算法,且以下算法都要实现

1) 先进先出算法(FIFO)

2) 最近最久未使用算法(LRU) 3) 最佳置换算法(OPT)

课题

五、编程序实现下述磁盘调度算法,并求出每种算法的平均寻道长度: 要求设计主界面以灵活选择某算法,且以下算法都要实现

1) 先来先服务算法(FCFS)

2) 最短寻道时间优先算法(SSTF) 3) 扫描算法(SCAN)

4) 循环扫描算法(CSCAN)

课题

六、编程模拟多进程共享临界资源: 要求产生3个进程: 1) 两个进程模拟需要进入临界区的用户进程,当需要进入临界区时,显示:“进程x请求进入临界区…”,同时向管理进程提出申请;申请返回,表示进入了临界区。在临界区中等待一段随机时间,并显示:“进程x正在临界区…”;当时间结束,显示:“进程x退出临界区…”,同时向管理进程提出退出申请;当申请返回,显示:“进程x已退出临界区。”

2) 一个进程作为原语的管理进程,接受其他进程的临界区进入请求:如果允许进入,则设置相应变量,然后返回;如果不允许进入,则进入循环等待,直到允许为止;

3) 对临界区的访问应遵循空闲让进、忙则等待、有限等待、让权等待的准则。 4) 进程间通信可以采用信号、消息传递、管道或网络通信方式。

课题七:为LINUX 设计一个简单的二级文件系统。要求做到以下几点:

1) 可以实现下列几条命令(至少4条)。

Login

用户登录 Dir

列文件目录 Create

创建文件 Delete

删除文件 Open

打开文件 Close

关闭文件 Read

读文件 Write

写文件

2) 列目录时要列出文件名、物理地址、保护码和文件长度。 3) 源文件可以进行读写保护。

课题八:存储管理---动态分区分配算法的模拟:

要求设计主界面以灵活选择某算法,且以下算法都要实现:首次适应算法、循环首次适应算法、最佳适应算法;

课题九:编程演示三种存储管理方式的地址换算过程:

1) 分页方式的地址换算 分段方式的地址换算 3) 段页式的地址换算

要求演示正确、清晰,编程所用工具不限。

课题

十、编写一个简单的端口扫描程序

目的:熟悉linux下socket、网络编程的基本方法;

任务:编写一个简单的程序,该程序可扫描局域网的某计算机开放了哪些端口;

课题十

一、编写一个基于TCP协议的客户/服务器程序

目的:熟悉linux下socket、网络编程的基本方法,掌握实现客户/服务器程序的编写方法; 任务:编写一个简单的程序,该程序可实现基于TCP协议的简单的客户/服务器方式。

课题十

二、编写一个使用数据报套接字的客户/服务器程序

目的:熟悉linux下socket、网络编程的基本方法,掌握客户/服务器程序的编写方法; 任务:编写一个简单的程序,该程序使用数据报套接字实现简单的客户/服务器方式。 课题十

三、在linux平台编写一个简单的网络监听程序

目的:熟悉网络数据包格式,熟悉捕获网络数据包的基本方法

任务:在linux平台编写一个简单的网络监听程序,该程序能捕获网络数据包,并根据需要分析相应的数据包。

课题十

四、编写一个简单的内核模块。

目的:动态可加载内核模块是我们动态扩展内核功能的一种方便灵活的方式,可用来实现一种文件系统、一个驱动程序、或其它内核上层的功能。 基本要求:

1) 该模块至少需要有两个函数:一个是init_module()函数,在把模块装载到内核时被调用,向内核注册模块所提供的新功能;另一个是cleanup module()函数,在卸载模块时被调用,其任务是清除init_module()函数所注册的功能。编写完成后进行该模块的编译、装载和卸载操作。编写一个用户空间的程序来测试是否成功。

2) 进一步的要求:向上面模块中再添加一些自己设计实现的新函数新功能;编写一个用户空间的程序来测试你的模块能否实现自己添加的功能。

课题十

五、编写一个简单的命令解释器—模拟shell功能 基本要求

1) 可打开提示符,并获取用户输入的指令可解析指令 3) 可寻找命令文件 4) 可执行基本的命令

课题十

六、实现系统状态监测工具

目的:实现程序,通过获取/proc文件系统所提供的系统信息,检查系统当前的各种状态信息。 要求:通过在命令行运行该程序,可获取以下信息:

1) CPU类型、型号、内核版本等信息从系统启动至今的时间等 3) 内存总容量及当前可用内存量 4) 系统平均负载

5) 支持的文件系统类型

6) 系统正在使用的module信息

附件2:课程设计题目

1.中文输入法程序 2.文件管理系统 3.线程管理

4.Windows进程多种同步案例演示 5.各种Window或Linux驱动程序编程 6.基于共享内存的进程之间的通信 7.文件加密

8.PE文件结构解析 9.异常处理系统 10.作业管理 11.中断驱动程序

12.可执行程序的加壳和脱壳 13.LRU动态内存管理模拟 14.注册表管理程序 15.内存管理程序 16.多系统启动程序

17.CPU的保护运行模式切换操作 18.扫描病毒算法模拟 19.木马扫描算法 20.硬盘碎片清理程序 21.程序卸载工具

22.文件系统FAT、NTFS、光盘、U盘分析程序 23.程序补丁 24.程序插件 25.文件压缩程序 26.文件备份系统 27.文件切割和组合 28.CPU参数监控程序 29.进程监控工具 30.文件系统搜索 31.系统监控软件 32.计算机看门狗 33.文件同步软件 34.个人信息同步软件 35.DLL文件创建和安装 36.小型操作系统编写 37.虚拟光驱软件 38.网络端口监测

39.内存管理——页面置换算法

附录3:课程设计封皮

仲恺农业技术学院

课程设计报告

课程名称:操作系统

实验题目:TCP/IP编程-网络聊天

院 系:计算机科学与工程学院 班 级: 2011级 ***班 姓 名: 张幸平学 号: *************

二○○八年七月二十日

第15篇:操作系统课程设计报告

操作系统课程设计报告

专 业:计算机科学与技术 学 号: 姓 名: 提交日期:

操作系统课程设计报告

【设计目的】

(1)本实验的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能和内部实现。

(2)结合数据结构、程序设计、计算机原理等课程的知识,设计一个二级文件系统,进一步理解操作系统。

(3)通过分对实际问题的分析、设计、编程实现,提高学生实际应用、编程的能力 【设计内容】

为Linux系统设计一个简单的二级文件系统。要求做到以下几点: 1.可以实现下列几条命令:

login 用户登录

dir 列目录

create 创建文件

delete 删除文件

open 打开文件

close 关闭文件

read 读文件

write 写文件

cd 进出目录

2.列目录时要列出文件名,物理地址,保护码和文件长度 3.源文件可以进行读写保护 【实验环境】 Windows xp/7 C++/VC++

【相关知识综述】

1、文件系统

文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:文件系统的接口,对对象操纵和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。

2、位示图

位示图是利用二进制的一位来表示磁盘中的一个盘块的使用情况。当其值为“0”时,表示对应的盘块空闲;为“1”时,表示已经分配。有的系统把\"0\"作为盘块已分配的标记,把“1”作为空闲标志。(它们的本质上是相同的,都是用一位的两种状态标志空闲和已分配两种情况。)磁盘上的所有盘块都有一个二进制位与之对应,这样,由所有盘块所对应的位构成一个集合,称为位示图。

操作系统课程设计报告

【设计思路】

本文件系统采用两级目录,其中第一级对应于用户账号,第二级对应于用户帐号下的文件。另外,为了简便文件系统未考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容。

首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。

用户创建的文件,可以编号存储于磁盘上。如:file0,file1,file2„并以编号作为物理地址,在目录中进行登记。

【程序主要流程图】

验证是否成

功?

目录

右键进行选择 操作

新建目录新建文件打开文件

结束

开始登录删除属性 2

操作系统课程设计报告

【源程序清单】

typedef struct

//文件结构体 /*the structure of OSFILE*/ { int fpaddr;

/*file physical addre*/

int flength;

/*file length*/

int fmode;

/*file mode:0-Read Only;1-Write Only;2-Read and Write; 3-Protect;*/

char fname[MAXNAME];

/*file name*/ } OSFILE;

typedef struct

//用户文件目录结构体 user file directory /*the structure of OSUFD*/ { char ufdname[MAXNAME];

/*ufd name*/ OSFILE ufdfile[MAXCHILD];

/*ufd own file*/ }OSUFD;

typedef struct

//登陆

/*the structure of OSUFD\'LOGIN*/ { char ufdname[MAXNAME];

/*ufd name*/

char ufdpword[8];

/*ufd paword*/ } OSUFD_LOGIN;

typedef struct

//文件打开模式 /*file open mode*/ { int ifopen;

/*ifopen:0-close,1-open*/

int openmode;

/*0-read only,1-write only,2-read and write,3-initial*/ }OSUFD_OPENMODE;

void DeleteF() /*Delete File*/ { int i,j,k=0; char str[255],str1[255]; char fname[MAXNAME]; k=ExistD(dirname); //获取用户的序号

printf(\"Please input filename:\"); gets(fname); //获得需要打开的文件名fname

for(i=0;i

if (strcmp(strupr(ufd[k]->ufdfile[i].fname),strupr(fname))==0)

{

操作系统课程设计报告

}

}

void OpenF() /*Open File*/ { int i,k=0; char fname[MAXNAME]; //printf(\"\\n\\nC:\\%s>\",strupr(dirname)); k=ExistD(dirname); printf(\"Please input filename:\"); gets(fname); //获得需要打开的文件名fname

for(i=0;i

if (strcmp(strupr(ufd[k]->ufdfile[i].fname),strupr(fname))==0)

{

ifopen[k][i].ifopen=1; //打开文件

ifopen[k][i].openmode=ufd[k]->ufdfile[i].fmode; //将读写属性赋值

//test// printf(\"i=%d,k=%d\\n\",i,k);

///test// printf(\"openmode=%d\\n\",ifopen[k][i].openmode);

printf(\"Open file succefully!\\n\");

break; //打开文件则跳出循环

4 itoa(ufd[k]->ufdfile[i].fpaddr,str,10); //itoa函数,把数字转换成字符串

strcpy(str1,\"file\"); strcat(str1,str); strcpy(str,\"c:\\osfile\\file\"); strcat(str,str1); strcat(str,\".txt\"); //str为文件的物理路径

if(remove(str)==0)

//调用remove函数删除 第k个用户的第i个文件ufd[k]->ufdfile[i]

{

fpaddrno[ufd[k]->ufdfile[i].fpaddr] = 0; //位示图置为0,表示没被占用

for( j = i ;j

ufd[k]->ufdfile[j] = ufd[k]->ufdfile[j+1] ;

fcount[k] = fcount[k] - 1 ; //文件数-1

printf(\"Delete file succefully!\\n\");

//除了删除原文件,还要 删除dir中的东西

} else

printf(\"Delete file fail!\\n\"); break; }

操作系统课程设计报告

}

} }

void CloseF() /*Close File*/ {

int i,k=0; char fname[MAXNAME];

k=ExistD(dirname); printf(\"Please input filename:\"); gets(fname); //获得需要关闭的文件名fname

for(i=0;i

if (strcmp(strupr(ufd[k]->ufdfile[i].fname),strupr(fname))==0)

{

ifopen[k][i].ifopen=0; //关闭文件

ifopen[k][i].openmode=4; //fmode改为初始值4

printf(\"Close file succefully!\\n\");

break;

}

} }

void WriteF() /*Write File*/ { int i,k,n=0; char fname[MAXNAME]; char str[255],str1[255]; int flag=1;

if (strcmp(strupr(ltrim(rtrim(dirname))),\"\")==0)

{

printf(\"\\nError.Please convert to ufd dir before read.\\n\");

wgetchar=1;

return; } printf(\"\\nCaution:Open file first\\n\"); printf(\"Opened File(s) List:\\n\"); k=ExistD(dirname);

操作系统课程设计报告

for(i=0;i

//文件属性为只写或者是读写才能write

{

printf(\"%15s\",ufd[k]->ufdfile[i].fname);

n++; } if((n%4==0)&&(n!=0)) printf(\"\\n\");

} printf(\"\\n%d files openned.\\n\",n);

if (n==0) wgetchar=1; if(n!=0) { printf(\"\\nPlease input FileName:\"); gets(fname); ltrim(rtrim(fname)); i=ExistF(fname); if(i>=0) {

if(ifopen[k][i].ifopen==1)

{

if((ifopen[k][i].openmode==1) ||(ifopen[k][i].openmode==2))

{

itoa(ufd[k]->ufdfile[i].fpaddr,str,10);

strcpy(str1,\"file\");

strcat(str1,str);

strcpy(str,\"c:\\osfile\\file\");

strcat(str,str1);

strcat(str,\".txt\"); //物理路径

int length=0;

char c;

printf(\"Please input text(\\\'#\\\' stands for end):\\n\");

fp_file=fopen(str,\"ab+\"); //在文件末尾加 add bit

while((c=getchar())!=\'#\') //以#为结尾

{

fputc(c,fp_file);

if (c!=\'\\n\') length++;

}

//fprintf(fp_file,\"\\n\");

操作系统课程设计报告

fclose(fp_file);

ufd[k]->ufdfile[fcount[i]-1].flength += length;//原长度加输入长度

printf(\"\\n\\\'%s\\\' has been written succefully!\\n\",fname);

}

else

{

printf(\"\\nError.\\\'%s\\\' has been opened with WRITE ONLY mode.It isn\\\'t read.\\n\",fname);

wgetchar=1;

}

}

else

{

printf(\"\\nError.\\\'%s\\\' is in closing status.Please open it before read\\n\",fname);

wgetchar=1;

}

}

else

{

printf(\"\\nError.\\\'%s\\\' does not exist.\\n\",fname);

wgetchar=1;

} } }

操作系统课程设计报告

【测试结果】

1、创建用户

2、创建文件,并且打开读取文件

操作系统课程设计报告

3、写文件

4、删除文件

操作系统课程设计报告

【设计总结】

这两周的课程设计时间非常短,从中学到了很多知识,也为我们的学习提供了良好的实践平台。首先,通过老师的细心指导和同学们的相互帮助,让我对题目【二级文件系统】有了进一步了解。接下来,主要是研究老师所给的大部分代码,参考他的基本思路,并且思考每一个结构体在代码中的具体作用。这期间和一些同学交流了各自的思路,在交流中,大家渐渐的明确了这个程序的思路、框架结构等。我们所做的主要是补充了删除文件,打开文件,关闭文件,写文件这几个部分。

代码编写完了之后,实现了题目所要求的基本功能,但是在测试的过程中,还发现了这个程序存在各种各样的bug。不断的测试修改后,得到完善。

这次课设最大的收获在于:学会交流以及相互帮助。在大家的交流沟通之中,我们解决了一个又一个难题。

在这次课设中,我还意识到,要把这门课真真正正地学好,不单单只是为了能够应付考试,平时还要多加学习,多加努力才对。

【参考文献】

【1】C语言程序设计(第三版) 谭浩强

【2】计算机操作系统教程(第三版).张尧学 史美林 张高

【3】计算机操作系统,西安电子科技大学出版社,方敏主编,2004.8

第16篇:操作系统课程设计题目

辽宁科技大学操作系统课程设计指导书

一、课程设计目的和要求

本设计是专业基础课《操作系统》的课程设计。由于操作系统课的学时有限,安排实验的次数不多。为了进一步巩固实验成果,加强理论联系实际、分析问题、解决问题的能力,加深对操作系统的基本概念、原理、技术和方法的理解,特安排此次课程设计。它是操作系统课程的实践环节。由于具体的操作系统相当复杂,在短短的一周之内,不可能对所有管理系统进行详细地分析。因此,选择了操作系统中最重要的管理之一进程管理(或进程的死锁、页面置换算法)作为本设计的任务。另外,通过此次设计使学生在使用系统调用的同时,进一步了解系统内部是如何实现系统调用的全过程,使学生在更深层次上对操作系统有所了解。 要求:

1.在具有自主版权的Linux环境下,用c或c++语言,以及相关的系统调用,编程实现进程的创建、控制、软中断通信、管道通信等功能。2.利用某种高级语言编程实现银行家算法。

3.常用的页面置换算法有:最佳置换算法(Optimal)、先进先出法(Fisrt In First Out)、、最近最久未使用(Least Recently Used),至少实现其中的两种算法。

二、课程设计内容

设计题目1:进程管理及理解 (1)进程的创建

编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示“a”;子进程分别显示字符“b”和“c”。试观察记录屏幕上的显示结果,并分析原因。

(2)进程的控制

修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。

如果在程序中使用系统调用lockf(),来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。

(3)①编制一段程序,使其实现进程的软中断通信。

要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号;当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:

Child Proce11 is Killed by Parent! Child Proce12 is Killed by Parent!

父进程等待两个子进程终止后,输出如下的信息后终止: Parent Proce is Killed!

②在上面的程序中增加系统调用signal(SIGINT,SIG_IGN)和signal(SIGQUIT,SIG_IGN),观察执行结果,并分析原因。

(4)进程的管道通信

编制一段程序,实现进程的管道通信,

使用系统调用pipe()建立一个管道文件;两个子进程P1和P2分别向管道各写一句话: Child1 is sending a meage! Child2 is sending a meage!

而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。

要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。 设计题目2:银行家算法实现资源分配

要求如下:

(1)进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。 (2)要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列的功能。 (3)显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。

(4)可能用到的数据结构:

 可利用资源向量Available。它是一个含有m个元素的数组,其中每个元素代表一类可利用资源的数目。

 最大需求矩阵Max。n*m矩阵,表示n个进程的每一个对m类资源的最大需求。  分配矩阵Allocation 。n*m矩阵,表示每个进程已分配的每类资源的数目。  需求矩阵Need 。n*m矩阵,表示每个进程还需要各类资源数。 设计题目3:虚拟页面置换算法的实现

要求如下:

(1)至少实现OPT、FIFO、LRU三种置换算法中的两种。

(2)做成GUI界面最好,若不能,则要求界面尽量友好,便于操作。 (3)算法中涉及到的页面访问序列可以固定,也可以随机生成。

(4)在实现算法的同时要计算每种算法的缺页数。 (5)以表格的形式输出最终的页面置换结果。

注:以上三个题目任选其一,还可以自拟其它题目。

选择题目1的同学,应事先了解 (1) Linux的命令及使用格式;

可通过下面的几个任务熟悉有关文件(夹)操作的命令。

(2)在虚拟机vmware下让Linux加载U盘的方法。

(3)利用gcc、gdb编译、调试C/C++程序

第17篇:操作系统课程设计3

操作系统课程设计3 一. 银行家算法代码

package sheji;

import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;

import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField;

public cla Banker extends JFrame implements ActionListener{

JTable table1; Object[][] data; JPanel p0,p1,p11,p12,p13,p14,p2,p3,p31,p32,p33,p34,p4; JLabel t1,t2,t3,t4,t5,t6,t7,t8,t9;//t10输出安全序列省去

JButton b1,b2,b3,b6,b5; TextField text01,text02,text03,text5,text6; JTextField[] text1,text2,text3,text4; JTextArea text7;

String s1,s2 = new String(); int M,N,i,j,count = 0,flag = 0; int[][]Max,Need,Allocation; int[] Available,Work,Request,Temp;

public Banker(){ super(\"211213067 秦瑛 银行家算法模拟系统\"); p0 = new JPanel(); p1 = new JPanel(); p11 = new JPanel(); p12 = new JPanel(); p13 = new JPanel(); p14 = new JPanel(); p2 = new JPanel(); p3 = new JPanel(); p31 = new JPanel(); p32 = new JPanel(); p33 = new JPanel(); p34 = new JPanel(); p4 = new JPanel();

p0.setLayout(new GridLayout(4,1)); p1.setLayout(new GridLayout(4,1)); p3.setLayout(new GridLayout(4,1));

p1.add(p11); p1.add(p12); p1.add(p13); p1.add(p14);

p3.add(p31); p3.add(p32); p3.add(p33); p3.add(p34);

p0.add(p1); p0.add(p2); p0.add(p3); p0.add(p4);

t1=new JLabel(\"进程数\"); t2=new JLabel(\"资源数\"); t3=new JLabel(\"进程号\"); t4=new JLabel(\"已分配资源\"); t5=new JLabel(\"资源最大需求\"); t6=new JLabel(\"可用资源\"); t7=new JLabel(\"请求资源进程号\"); t8=new JLabel(\"请求资源为\"); t9=new JLabel(\"安全检测\");

b1=new JButton(\"确定\"); b2=new JButton(\"添加\"); b3=new JButton(\"确定\"); b5=new JButton(\"请求\"); b6=new JButton(\"安全检测\");

text1 = new JTextField[6]; text2 = new JTextField[6]; text3 = new JTextField[6]; text4 = new JTextField[6];

for(int i=0;i

text1[i] = new JTextField(4);

text2[i] = new JTextField(4);

text3[i] = new JTextField(4);

text4[i] = new JTextField(4); }

text01 = new TextField(4); text02 = new TextField(4); text03 = new TextField(4); text5 = new TextField(4); text6 = new TextField(50);

String[] columnNames1 = {\"进程号\",\"资源最大需求Max\",\"已分配的资源Allocation\",\"需要的资源Need\",\"可利用的资源Available\"}; data = new Object[100][5]; table1 = new JTable (data, columnNames1); table1.setPreferredScrollableViewportSize(new Dimension(550, 100)); table1.setRowHeight (20); table1.doLayout(); JScrollPane pane1 = new JScrollPane (table1);

text7 = new JTextArea(\" \",6,40); JScrollPane pane2 = new JScrollPane(text7); text7.setEditable(false);

p11.add(t1); p11.add(text01); p11.add(t2); p11.add(text02); p11.add(b1); p12.add(t3); p12.add(text03); p12.add(b2); p13.add(t4); for(int i=0;i

p13.add(text1[i]); p14.add(t5); for(int i=0;i

p14.add(text2[i]); p2.add(pane1);

p31.add(t6); for(int i=0;i

p31.add(text3[i]); p31.add(b3); p32.add(t7); p32.add(text5); p32.add(t8); for(int i=0;i

p32.add(text4[i]); p33.add(b6); p33.add(b5); p34.add(t9); p34.add(text6); p4.add(pane2);

b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); b5.addActionListener(this); b6.addActionListener(this);

p0.setBackground(Color.lightGray);

setContentPane (p0); this.setVisible(true); this.pack();

}

public void Diguisafe(int k,int n) {//递归求解安全序列函数

int m,a; if(k==n){

for(int j=0;j

Work[j] = Available[j];

if(Safe()==1){

for(a=0;a

s1 += Temp[a]+\"->\";

s1 +=Temp[a]+\"\"+\"\\n\";

count++;

for(int j=0;j

Work[j] = Available[j];

} } else

for(i=k;i

m=Temp[k];

Temp[k]=Temp[i];

Temp[i]=m;

Diguisafe(k+1,n);

m=Temp[k];

Temp[k]=Temp[i];

Temp[i]=m;

} }

public int Safe(){//求是否安全序列

int i; for(i=0;i

if(Small(Temp[i]-1)==1){

CountWork(Temp[i]-1);

continue;

}

else break;

} if(i==M)return 1; else return 0;

}

public void CountWork(int i){//计算工作向量函数

for(int j=0;j

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

}

public int Small(int i){//判断是否满足需求函数

int flag = 0; for(int j=0;j

if(Need[i][j]

else{

flag =0;

break;

} } return flag;

} public int Req_need(){//判断是否满足需求资源函数

int flag = 0; for(int i=0;i

if(Need[j-1][i]>=Request[i])flag = 1;

else{

flag=0 ;break;

} } return flag; }

public int Req_ava(){//判断是否满足可用资源数

int flag=0; for(int i=0;i

if(Available[i]>=Request[i]) flag=1;

else

{

flag=0;break;

} } return flag; }

public void Changedata(){//预分配函数

String s_available = new String(); for(int i=0;i

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

Allocation[j-1][i] = Allocation[j-1][i]+Request[i];

Need[j-1][i] = Need[j-1][i]-Request[i];

s_available += Available[j]+\" \"; } data[0][4] = s_available; table1.repaint(); text6.setText(\" \"); text7.setText(\" \"); }

public void Qingqiu(){//资源请求函数 count = 0; if(Req_need()==1&&Req_ava()==1){//不满足需求

Changedata(); //预分配

} else{

s2 =\"不能分配\";

text6.setText(s2); } }

public void actionPerformed(ActionEvent e){ if(e.getSource()==b1){

M = Integer.parseInt(text01.getText());

N = Integer.parseInt(text02.getText());

Max = new int[M][N];

Allocation = new int[M][N];

Need = new int[M][N];

Available = new int[N];

Request = new int[N];

Work = new int[N];

Temp = new int[M]; }

if(e.getSource()==b2){ i = Integer.parseInt(text03.getText()); int max,allocation; String s_max,s_need,s_allocation; s_max = new String(); s_need = new String(); s_allocation = new String();

for(int j=0;j

for(int j=0;j

if(e.getSource()==b3){ int available; String s_available=new String(); for(int j=0;j

available = Integer.parseInt(text3[j].getText());

Available[j] = available;

s_available += Available[j]+\" \"; } data[0][4] = s_available; table1.repaint(); }

if(e.getSource()==b5) { flag =1; //请求

int request; text6.setText(\" \"); text7.setText(\" \"); j = Integer.parseInt(text5.getText()); for(int i=0;i

request = Integer.parseInt(text4[i].getText());

Request[i] = request; } Qingqiu(); }

if(e.getSource()==b6){//安全序列

s1=new String();

count=0; Diguisafe(0,M-1); if(count==0&&flag==0){

s2 =\"系统处于不安全状态,不能请求\"; } else if(count==0&&flag==1){

s2 =\"系统处于不安全状态,不能分配\"; } else

s2=\"有\"+count+\"个安全序列,\"; text7.setText(s1); text6.setText(s2); flag = 0; } } public static void main(String[] args){

new Banker(); } } 二. 运行界面

进入界面:

数据填充检测:

第18篇:《操作系统课程设计》指导书分析

《操作系统课程设计》实验指导

课程设计一:进程调度

1、设计目的

(1) 要求学生设计一个模拟进程调度的算法 (2) 理解进程控制块的结构 (3) 理解进程运行的并发性

(4) 掌握进程调度的三种基本算法 注:三种算法任选一种编程实现。

2、设计要求

在多道程序运行环境下,进程数目一般多于处理机数目,使得进程要通过竞争来使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之运行,分配处理机的任务是由进程调度程序完成的。一个进程被创建后,系统为了便于对进程进行管理,将系统中的所有进程按其状态,将其组织成不同的进程队列。于是系统有运行进程队列、就绪进程队列和各种事件的进程等待队列。进程调度的功能就是从就绪队列中挑选一个进程到处理机上运行。进程调度的算法有多种,常用的有优先级调度算法、先来先服务算法、时间片轮转算法。

进程是程序在处理机上的执行过程。进程存在的标识是进程控制块(PCB),进程控制块结构如下:

Typeedef struct node {

Char name[10];

/*进程标识符*/

Int prio;

/*进程优先数*/

Int round;

/*进程时间片轮转时间片*/

Int cputime

/*进程占用CPU时间*/

Int needtime

/*进程到完成还需要的时间*/

Int count;

/*计数器*/

Char state;

/*进程的状态*/

Struct node

*next;

/*链指针*/ }PCB; 系统创建一个进程,就是由系统为某个程序设置一个PCB,用于对该进程进行控制和管理。进程任务完成,由系统收回其PCB,该进程便消亡。每个进程可以有三个状态:运行态、就绪态和完成状态。

用VC编写一个程序实现进程调度算法,模拟进程调度的过程,加深对进程控制块概念和进程调度算法的理解。

(1) 进程调度算法采用优先数调度算法。 (2) 采用动态优先数法确定进程的优先级别。

(3) 设计三个链队列,分别用来表示运行队列、就绪队列和完成队列。

(4) 用户输入进程标识符以及进程所需要的时间,申请空间存放进程PCB信息。

优先数调度算法为每个进程设一个优先数,它总是把处理机给就绪队列中具有最高优先权的进程。常用的算法有静态优先数法和动态优先数法。

动态优先数法,使进程的优先权随时间而改变。初始的进程优先数取决于进程运行所需

要的时间,时间大,则优先数低。可采取将进程优先数定为一个较大的数(50)减去进程运行所需要的时间。随着进程的运行对优先数进行调整,每次运行时都是从就绪队列中选取优先数最大的进程运行,所以,就将就绪队列按照优先数的大小从高到低排序,这样,每次选队首进程即可。

进程每执行一次,优先数减一个数(自定),CPU时间数加1,进程还需要的时间减1。如果进程所需时间为0,说明进程运行完毕,将其状态变为完成状态“F”,将此进程PCB插入到完成队列中,若就绪队列不空,则将就绪队列中的第一个PCB变为运行状态。进程若没有完成,则将其优先数和就绪队列中的第一个PCB的优先数作比较,如果小,则将其变为就绪态,插入到就绪队列中适当的位置,将就绪队列中的第一个PCB变为运行态投入运行,重复上述过程,直到就绪队列为空,所以进程成为完成状态为止。

1 时间片轮转算法完成进程的调度

设计要求:

(1)进程调度算法采用时间片轮转算法。

(2)设计三个链队列,分别用来表示运行队列、就绪队列和完成队列。

(3)用户输入进程标识符以及进程所需要的时间,申请空间存放进程PCB信息。 (4)输出格式和上面的一样

时间片轮转调度:具体做法是调度程序每次把CPU分配给就绪队列首进程使用一个时间片。当这个时间片结束时,就强迫一个进程让出处理器,让它排列到就绪队列的尾部,等候下一轮的调度。实现这种调度要使用一个间隔时钟。当一个进程开始运行时,就将时间片的值置入间隔时钟内,当发生间隔时钟中断时,就表明该进程连续运行的时间已超过一个规定的时间片。此时,中断处理程序就通知处理器调度进行处理器的切换工作。

2 用先来先服务算法完成进程的调度

设计要求:

(1)进程调度算法采用先来先服务算法。

(2)设计三个链队列,分别用来表示运行队列、就绪队列和完成队列。

(3)用户输入进程标识符以及进程所需要的时间,申请空间存放进程PCB信息。 (4)输出格式和上面的一样 先来先服务算法:按照进程进入就绪队列的先后次序来分配处理器。先进入就绪队列的进程优先被挑选,运行进程一旦占有处理器将一直运行下去直到运行结束或被阻塞,这是一种非剥夺式调度。

课程设计二:磁盘调度

1、设计目的

(1) 要求学生设计一个模拟磁盘调度的程序。 (2) 理解磁盘调度过程中的三个时间段 (3) 理解磁盘调度的三种算法

2、实验原理

共享设备的典型代表为磁盘,磁盘物理块的地址由柱面号、磁头号、扇区号来指定,完成磁盘某一个物理块的访问要经过三个阶段:寻道时间Ts、旋转延迟时间Tw和读写时间Trw。

寻道时间Ts是磁头从当前磁道移动到目标磁道所需要的时间;旋转延迟时间Tw是当磁头停留在目标磁道后,目标物理块从当前位置旋转到磁头位置的时间;读写时间Trw是目标物理块内容与内存中对应交换的时间。磁盘调度的原则是公平和高吞吐量,衡量指标有访问时间T和平均访问时间Ta:

T=Ts+Tw+Trw

Ta=Tsa+Twa+Trwa 寻道时间和旋转延迟时间成为调度算法的主要考虑因素。减少访问时间就是要减少寻道时间和旋转延迟时间。

3、设计要求

(1) 设计一个函数完成先来先服务的磁盘调度功能。

(2) 设计一个函数完成最短寻道时间优先的磁盘调度功能。 (3) 设计一个函数完成电梯算法的磁盘调度功能。

(4) 从键盘输入一组磁盘访问序列,选择三种算法中的一种,输出其磁头移动的总的磁道数

课程设计三:主存空间的分配与回收

1、设计目的

主存是中央处理器能直接存取指令和数据的存储器,能否合理地利用主存,在很大程度上将影响到整个计算机系统的性能。主存分配是指在多道作业和多进程环境下,如何共享主存空间。主存回收是指当作业执行完毕或进程运行结束后将主存空间归还给系统。主存分配与回收的实现是与主存储器的管理方式有关。本次设计主要是为了帮助理解主存空间的分配与回收的几种算法。

(1) 掌握最先适应分配算法 (2) 掌握最优适应分配算法 (3) 掌握最坏适应分配算法

2、设计要求

用户提出内存空间请求,系统根据申请者要求,按照最先适应算法的分配策略分析主存空间的使用情况,找出能满足请求的空闲区,分给申请者,当程序执行完毕时,系统要收回它所占用的内存空间。

建立空闲区数据文件,空闲区数据文件包括若干行,每行有两个字段:起始地址、内存块大小(均为整数),各字段以逗号隔开。下面是一个空闲区数据文件的示例:

0,

10 10,

08 18, 10 28, 06 34, 10 44, 09 读取空闲区数据文件,建立空闲区表并在屏幕上显示空闲区内存状态,空闲区表记录了可供分配的空闲内存的起始地址和大小,用标志位指出该分区是否是未分配的空闲区。

接收用户的内存申请,格式为:作业名、申请空间的大小。

按照内存分配算法中的一种方法选择一个空闲区,分割并分配,修改空闲区表,填写内存已分配区表(起始地址、长度、标志位),其中标志位的一个作用是指出该区域分配给哪个作业。

作业结束后回收内存。 分区表的结构如下: Typedef struct node { Int start;

Int length;

Char tag[20]; }job

设计内容:

1 设计一个内存分配回收的函数使用最优适应分配算法 2 设计一个内存分配回收的函数使用最坏适应分配算法 3设计一个内存分配回收的函数使用最先适应分配算法 用户提出内存空间请求,系统根据申请者要求,分别使用上述算法分析内存空间的使用情况,找出合适的空闲区,分给申请者,当作业执行完毕后,系统收回它所占用的内存空间。

课程设计四:P,V操作

设计要求:

编程模拟实现下列任一问题:

1.桌上有一盘子,可以存放一个水果。爸爸总是放苹果到盘子中,而妈妈总是放香蕉到盘子中;一个儿子专等吃盘中的香蕉,一个女儿专等吃盘中的苹果。请用P,V操作实现上述问题的解。

分析:在本题中,爸爸、妈妈、儿子和女儿共用一个盘子,盘子一次只能放一个水果。当盘子为空时,爸爸和妈妈都可以试着将一个水果放入盘中,但一次只能有一人成功放入水果。若放入盘子中的是香蕉,则允许儿子吃,女儿必须等待;若放入盘子中的是苹果,则允许女儿吃,儿子必须等待。

在本题中,应设置3个信号量dish、apple、banaba,信号量dish表示盘子是否为空,其初值为1;信号量apple表示盘中是否有苹果,其初值为0;信号量banana表示盘中是否有香蕉,其初值为0。进程之间的同步描述如下:

Semaphore dish=1; Semaphore apple,banana=0; Main() {

cobegin

father();

mother();

son();

daughter();

coend } Father()

mather() {

{

while(true)

while(true)

{

{

p(dish);

p(dish);

将苹果放入盘中;

将香蕉放入盘中;

v(apple);

v(banana);

}

} }

} Son()

daughter() {

{

while(true)

while(true)

{

{

p(banana);

p(apple);

从盘中取出香蕉;

从盘中取出苹果;

v(dish);

v(dish);

吃香蕉;

吃苹果;

}

}

}

2、设公共汽车上,司机和售票员的活动分别是: 司机的活动:启动车辆;正常行车;到站停车。

售票员的活动:关车门;售票;开车门。

在汽车不断的到站、停站、行驶过程中,用信号量和P,V操作实现它们的同步。

分析:在汽车行驶过程中,司机活动与售票员活动之间的同步关系为:售票员关车门后向司机发开车信号,司机接到开车信号后启动车辆,在汽车正常行驶过程中售票员售票,到站时司机停车,售票员在车停后开车门让乘客下车。因此司机启动车辆的动作必须与售票员关车门的动作取得同步;售票员开车门的动作也必须与司机停车取得同步。

在本题中,应设置两个信号量s

1、s2,s1表示是否允许司机启动汽车,其初值为0;s2表示是否允许售票员开车门,其初值为0。这两个活动的同步用P,V原语描述如下:

Semaphore s1,s2=0;

Main() {

cobegin

driver();

busman();

coend } Driver()

busman()

{

{

while(true)

while(true)

{

{

p(s1);

关车门;

启动车辆;

v(s1);

正常行车;

售票;

到站停车;

p(s2);

v(s2);

开车门;

}

上下乘客;

}

}

}

3,、读者写者问题(算法略)

4、多个生产者与消费者问题(算法略)

5、哲学家就餐问题(算法略)

课程设计五:银行家算法

1、设计目的

(1) 了解多道程序系统中,多个进程并发执行的资源分配。

(2) 掌握死锁产生的原因、产生死锁的必要条件和处理死锁的基本方法。 (3) 掌握预防死锁的方法,系统安全状态的基本概念。

(4) 掌握银行家算法,了解资源在进程并发执行中的资源分配策略。 (5) 理解避免死锁在当前计算机系统不常使用的原因

2、设计要求

在多道程序系统中,虽可借助于多个进程的并发执行来改善系统的资源利用率,提高系统的吞吐量,但可能发生一种危险----死锁。死锁是指多个进程在运行中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法向前推进。银行家算法是最具有代表性的避免死锁的算法,它的基本思想是分配资源之前,判断系统是否是安全的,若是才分配资源。

设计一个n个并发进程共享M个系统资源的程序实现银行家算法。要求包含: (1) 简单的选择界面

(2) 能显示当前系统资源的占用和剩余情况

(3) 为进程分配资源,如果进程要求的资源大于系统剩余的资源,不予分配并且提示分配不成功。

(4) 撤销作业,释放资源。

3、算法描述(略)

4、所用的数据结构说明 (1) 银行家所能提供的资源

Type struct node{ Int a; Int b; Int c; Int remain_a; Int remain_b; Int remain_c; }bank;

(2) 进程所占用的资源

Typedef struct node1{ Chan name[20]; Int a; Int b; Int c; Int need_a; Int need_b; Int need_c; }proce

第19篇:操作系统课程设计六种算法

《计算机操作系统》

学号:班级:软技姓名:张靖伟 课 程 设 计 报 告

4班

1367003270

1 实验:进程调度算法——时间片轮转算法 2 实验:银行家算法3 实验:分区分配算法——4 实验:页面置换算法——5 实验:磁盘调度算法——

BF和FF

FIFO和LRU SCAN和SSTF 1实验:进程调度算法——时间片轮转算法

1.实验设计说明

用时间片轮转算法模拟单处理机调度。

(1) 建立一个进程控制块PCB来代表。PCB包括:进程名、到达时间、运行时间和进程后的状态。

进程状态分为就绪(R)和删除(C)。

(2) 为每个进程任意确定一个要求运行时间和到达时间。

(3) 按照进程到达的先后顺序排成一个队列。再设一个指针指向队首和队尾。 (4) 执行处理机调度时,开始选择对首的第一个进程运行。 (5) 执行: a)输出当前运行进程的名字;

b)运行时间减去时间片的大小。

(6) 进程执行一次后,若该进程的剩余运行时间为零,则删除队首,并将该进程的状态置为C;若不为空,则将向后找位置插入。继续在运行队首的进程。

(7) 若进程队列不空,则重复上述的(5)和(6)步骤直到所有进程都运行完为止。

2.实验代码

/*****************时间片轮转调度算法*******************/ #include #include #include #define N 10 int time=0; bool spe=false; typedef struct pcb /*进程控制块定义*/ {

char pname[N]; int runtime; /*进程名*/ /*服务时间*/ int arrivetime; /*到达时间*/ char state; /*进程状态*/ struct pcb*next;/*连接指针*/ }PCB; typedef struct back_team/*后备队列定义*/ { PCB*first,*tail; }BACK_TEAM; typedef struct pre_team/*就绪队列定义*/ { PCB*first,*tail; }PRE_TEAM; PCB*creat()/*创建PCB*/ {

char s[N]; printf(\"请输入进程名:\\n\"); scanf(\"%s\",s); printf(\"请输入进程服务时间(/秒):\\n\"); int t; scanf(\"%d\",&t); PCB*p=(PCB*)malloc(sizeof(PCB)); strcpy(p->pname,s); p->runtime=t; printf(\"请输入进程到达时间(/秒):\\n\"); scanf(\"%d\",&t); p->arrivetime=t; p->state=\'R\'; p->next=NULL; getchar(); return p; } PCB*copy(PCB*p)/*复制一个进程*/ {

} PCB*getnext(PCB*p,BACK_TEAM*head)/*得到队列中下一个进程*/ {

} void del(BACK_TEAM*head,PRE_TEAM*S)/*释放申请的空间*/ {

PCB*p=head->first->next; while(p) { free(head->first); head->first=p; PCB*s=head->first; if(!p) return NULL; if(!p) return NULL; PCB*s=(PCB*)malloc(sizeof(PCB)); strcpy(s->pname,p->pname); s->next=NULL; s->arrivetime=p->arrivetime; s->runtime=p->runtime; s->state=p->state; return s; while(strcmp(s->pname,p->pname)) s=s->next; return s->next;

} } p=p->next; head->first=head->tail=NULL; free(head); free(S); BACK_TEAM*creatbt(BACK_TEAM*head)/*创建后备队列*/ {

} bool recognize(PRE_TEAM*s1)/*判断运行是否结束*/ {

if(!s1||!s1->first) return false; PCB*p=creat(); if(!head->first) else head->tail->next=p; head->first=p; head->tail=p; return head; if(s1->first==s1->tail)

if(s1->first->state!=\'C\') else return false; return true; PCB*test=s1->first; while(test!=s1->tail&&(test->state!=\'C\')) test=test->next; if(test==s1->tail)

} return true; else return false; PCB*run(PRE_TEAM*s)/*在CPU中运行*/ {

if(!s->first) {

} printf(\"%d\\t%s\\t\",time,s->first); s->first->runtime--; time++; if(s->first->runtime

} PCB*p=s->first; s->first->state=\'C\'; printf(\"%c\\n\",s->first->state); s->first=p->next; free(p); if(!s->first) {

} goto next; s->tail=NULL; spe=false; return NULL; spe=false; return NULL; printf(\"%c\\n\",s->first->state); next:PCB*head=s->first;

} int CREAT(PCB*HEAD,PRE_TEAM*head2,bool*test,PCB*c)/*创建就绪队列*/ {

int i=0; if(!head2->first)

if(HEAD) {

} if(c) {

} head2->first=head2->tail=HEAD; return 1; head2->first=c; c->next=HEAD; head2->tail=HEAD; return 1; s->first=head->next; if(!s->first) {

} head->next=NULL; return head; s->tail=NULL; spe=true; if(head2->first==head2->tail) {

} else {

} if(*test) {

} if(c) {

} head2->tail->next=c; head2->tail=c; if(head2->first->arrivetime!=time) for(i=0;ifirst->arrivetime;i++,time++); *test=false; return 1; if(c) {

} if(c->arrivetime!=time) {

} head2->tail->next=c; head2->tail=c; time++; return 1; if(HEAD) { head2->tail->next=HEAD;

} } head2->tail=HEAD; return 1; int main(void) {

BACK_TEAM*head1=(BACK_TEAM*)malloc(sizeof(BACK_TEAM)); head1->first=head1->tail=NULL; PRE_TEAM *head2=(PRE_TEAM*)malloc(sizeof(PRE_TEAM)); head2->first=head2->tail=NULL; char ask; int num=0; bool test=true; do{

printf(\"要创建进程吗(y/n):\"); if((ask=getchar())==\'y\'||ask==\'Y\') {

} else if(ask==\'n\'||ask==\'N\') else return 1; break; head1=creatbt(head1); num++; }while(1); PCB*p=copy(head1->first); PCB*HEAD=NULL; head2->first=head2->tail=copy(head1->first); printf(\"时刻\\t进程名\\t状态\\n\");

} while(spe||recognize(head2)) {

} del(head1,head2); return 1; CREAT(HEAD,head2,&test,p); HEAD=run(head2); p=copy(getnext(p,head1)); 3.实验结果

和不马上运行:

当有两个进程的时候

当有多个进程的时候:

4.实验结果分析

RR算法:每次调度时,把CPU分配给队首进程,并且令其执行一个时间片,时间片的大小从几个ms到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便依据此信号来停止该进程的执行;并且把它送往就绪队列的队尾;然后,再把处理剂分配给就绪队列中的新队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一个给定时间内均能获得一时间片的处理机执行时间。换言之,系统能在给定的时间内相应所有用户的请求.2实验:银行家算法

1.实验设计说明

1.该算法通过建立几个简单的二维数组Available,Max,Allocation,Need简单的模拟银行家算法和安全性算法,每个二维数组默认[][0]为A资源,[][1]为B资源,[][2]为C资源,默认有5个进程

2.程序首先要输入各个进程的三种资源的情况,包括每个进程最大的需求量,已经分配的资源量和现在还需要的资源量,以及系统现在剩余的资源量。3.程序会判断输入的信息是否在程序的规定范围内,正确才运行。

4.在执行安全算法开始时,Work∶=Available; ② Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]∶=false; 当有足够资源分配给进程时, 再令Finish[i]∶=true 5.从进程集合中找到一个能满足下述条件的进程: Finish[i]=false;并且 Need[i,j]≤Work[j]; 若找到, 执行6, 否则,执行7。

6.当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

Work[j]∶=Work[i]+Allocation[i,j]; Finish[i]∶=true; 然后继续执行5。

7.如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。

2.实验代码

#include int Available[3],Max[5][3],Allocation[5][3],Need[5][3]; bool Safe(int p) { int Work[3]={Available[0],Available[1],Available[2]}; int Finish[5]={0,0,0,0,0}; int i=0,m,num=0; if(Need[p][0]||Need[p][1]||Need[p][2])

return false; printf(\"p%d可以运行\\n\",p); Work[0]+=Allocation[p][0]; Work[1]+=Allocation[p][1]; Work[2]+=Allocation[p][2]; Finish[p]=1; while(num

if(!Finish[i]&&(Need[i][0]

{

printf(\"p%d可以运行\\n\",i);

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

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

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

Finish[i]=1;

}

num++;

i=(i+1)%5;

if(i==p)

i++; } for(m=0;m

if(Finish[m]==0)

break; if(m==5)

return true; else {

printf(\"系统处于不安全状态!\\n\");

return false; } } void Banker(int p,int i,int j,int k) { int able[3]={Available[0],Available[1],Available[2]}; int need[3]={Need[p][0],Need[p][1],Need[p][2]}; int allocation[3]={Allocation[p][0],Allocation[p][1],Allocation[p][2]}; if(i

if(i

{

Available[0]-=i;

Available[1]-=j;

Available[2]-=k;

Allocation[p][0]+=i;

Allocation[p][1]+=j;

Allocation[p][2]+=k;

Need[p][0]-=i;

Need[p][1]-=j;

Need[p][2]-=k;

if(!Safe(p))

{

Available[0]=able[0],Available[1]=able[1],Available[2]=able[2];

Need[p][0]=need[0],Need[p][1]=need[1],Need[p][2]=need[2];

Allocation[p][0]=allocation[0],Allocation[p][1]=allocation[1],Allocation[p][2]=allocation[2];

printf(\"系统可能发生死锁!\\n\");

}

}

else

printf(\"等待!系统资源不足!\\n\"); else

printf(\"错误!申请的资源错误!\\n\"); } int main(void) { int i,j,k=0,p; printf(\"请输入进程的三种资源的情况max{a,b,c} allocation{a,b,c} need{a,b,c}:\\n\"); for(i=0;i

for(j=0;j

scanf(\"%d\",&Max[i][j]);

for(j=0;j

scanf(\"%d\",&Allocation[i][j]);

for(j=0;j

scanf(\"%d\",&Need[i][j]); } printf(\"请输入Available{a,b,c}情况:\"); for(i=0;i

scanf(\"%d\",&Available[i]); printf(\"Max\\tAllo\\tNeed\\tAvai\\n\"); for(i=0;i

for(j=0;j

printf(\"%d \",Max[i][j]);

printf(\"\\t\");

for(j=0;j

printf(\"%d \",Allocation[i][j]);

printf(\"\\t\");

for(j=0;j

printf(\"%d \",Need[i][j]);

printf(\"\\t\");

if(k!=4)

printf(\"\\n\");

k++; } for(i=0;i:\"); scanf(\"%d %d %d %d\",&p,&i,&j,&k); if(p>=0&&p

4.实验结果分析

这个实验只是简单的演示了进程申请资源之后的进程运行的其中一个运行序列,因为这个算法课本上已经有详细的解说,所以这个程序并没有把算法的过程展现出来,只展现了进程的运行序列结果,另外,如果申请错误的话程序会有不同的结果

有时会发生死锁

3 实验:分区分配算法——BF和FF 1.实验设计说明

1.这个算法模拟的是对内存空间的管理,这个程序用了一个简单的二维数组模拟分区表。2.程序首先要输入固定的五个分区的大小和始址,其次要输入作业的大小和实现的算法,由于这个程序把FF和BF放到一个程序中,便于比较两个算法。

首次适应算法FF(First Fit) 把分区大于等于请求作业请求的分区分给请求者,余下部分仍留在空闲区中,然后修改分区表。然后打印出分配后的分区表 最佳适应算法BF(Best Fit)

首先把分区表按空间大小从小到大排序。然后把分区大于等于请求作业请求的分区分给请求者,余下部分仍留在空闲区中,然后修改分区表。然后打印出分配后的分区表

2.实验代码 #include int table[5][3]; void FirstFit(int job[3],int ta[5][3]) {

int i,j; for(j=0;j

for(i=0;i

if(ta[i][1]>=job[j]) {

} ta[i][1]-=job[j]; ta[i][2]+=job[j]; break; if(i==5)printf(\"内存不足!请等待!\\n\");

} printf(\"空闲区\\t大小\\t始址\\n\"); for(j=0;j

} for(i=0;i

int j1,temp1,temp2,temp3,i,j; for(j1=0;j1

for(i=0;i

for(j=0;j

if(table[j][1]>table[j+1][1]) { temp1=table[j][0];temp2=table[j][1];temp3=table[j][2];

table[j][0]=table[j+1][0];table[j][1]=table[j+1][1];table[j][2]=table[j+1][2];

}

table[j+1][0]=temp1;table[j+1][1]=temp2;table[j+1][2]=temp3;

} if(i==5)printf(\"内存不足!请等待!\\n\"); printf(\"空闲区\\t大小\\t始址\\n\"); for(j=0;j

} for(i=0;i

} for(i=0;i

if(table[i][1]>=job[j1]) {

} table[i][1]-=job[j1]; table[i][2]+=job[j1]; break; printf(\"\\n\"); void main() {

int table1[5][3],job[3],j,i; printf(\"请输入5个空分区的大小和始址:\"); for(i=0;i

} for(j=0;j

} printf(\"请输入3个要运行作业的大小:\"); for(i=0;i

} scanf(\"%d\",&table[i][j]); table1[i][j]=table[i][j]; printf(\"\\n\"); printf(\"请输入要实现的算法1(FF)2(BF):\");

} char c; scanf(\"%d\",&i); getchar(); if(i==1) {

} else

if(i==2) {

} BestFit(job); printf(\"还要实现FF吗(y/n)\"); if((c=getchar())==\'y\') FirstFit(job,table1); FirstFit(job,table1); printf(\"还要实现BF吗(y/n)\"); if((c=getchar())==\'y\') BestFit(job); 3.实验结果

4.实验结果分析

首先输入分区表的分区情况,然后输入运行作业的大小,选择要实现的算法。 第一个作业是96,所以找到第四个分区,第四个分区变为122,316,接着到第二个作业20,然后把第一个分区分给第二个作业,则第一个分区信息变为122,316,到第三个作业时,由于内存表中没有比第三个请求的分区还大的分区,所以会提示内存不足;

然后到BF算法,因为是按空间大小排序的,所以第一个作业96被分配给了已经排好序的内存为96的第五个分区,第二个作业被分配给大小为36的分区,第三个作业被分配给内存大小为218的分区,然后又对剩余空间再次排队,用来给下一批作业分配。

4 实验:页面置换算法——FIFO和LRU 1实验设计说明

程序设置了两个结构体,freeBlock和jobQueue,其中freeBlock代表物理块,初次创建物理块时,物理块的计时器time=0,还有代表作业的index=-1; 物理块有添加和删除的功能,每一次添加或删除都要初始化物理块。并且可以重复添加和删除,这样可以很好的测试算法的性能。 2.算法设计的思想是:进入物理块时间越长的则物理块的计时器数值越大,如果物理块中有要访问的页面,则那个含页面的物理块的计数器变成1;并且物理块要满才会发生置换,于是设置了物理块计数器Time;

2.实验代码 #include #include typedef struct freeBlock { int index,time; struct freeBlock*next; }freeBlock; typedef struct jobQueue { int index; struct jobQueue*next; }jobQueue; jobQueue*creat(jobQueue*head,int num) {

jobQueue*job=(jobQueue*)malloc(sizeof(jobQueue)); job->index=num; job->next=NULL; if(!head) {

jobQueue*j=head; while(j->next) j=j->next; j->next=job; head=job; else

} } return head; freeBlock*creat(freeBlock*head) {

} freeBlock*inse(freeBlock*head) {

} freeBlock*dele(freeBlock*head) { freeBlock*test=head; while(test) {

} freeBlock*free=(freeBlock*)malloc(sizeof(freeBlock)); free->index=-1;free->time=0; free->next=head; head=free; return head; test->index=-1;test->time=0; test=test->next; freeBlock*free=(freeBlock*)malloc(sizeof(freeBlock)); free->index=-1;free->time=0; free->next=NULL; if(head) free->next=head; head=free; return head;

} freeBlock*test=head; while(test) {

} freeBlock*f=head; head=f->next; free(f); return head; test->index=-1;test->time=0; test=test->next; bool check(freeBlock*free,int j) {

} void LRU(freeBlock*free,jobQueue*job) {

int size=0,Time=0,time=0; jobQueue*jtest=job; freeBlock*ftest=free; while(ftest) { freeBlock*f=free; while(f) {

} return false; if(f->index==j) return true; f=f->next;

} size++; ftest=ftest->next; printf(\"LRU置换页面为:\"); while(jtest) {

ftest=free; while(ftest) {

} ftest=free; while((time==size)&&ftest) { if(check(free,jtest->index)) { if(ftest->index==jtest->index) {

} ftest->time++; if(Timetime) Time=ftest->time; time++; ftest=ftest->next; ftest->index=jtest->index; ftest->time++; time=0; break; ftest->time=0; if(ftest->index==-1)

}

}

}

} time=0; Time=0; break; if(ftest->time==Time) {

} ftest=ftest->next; printf(\"%d \",ftest->index); ftest->index=jtest->index; ftest->time=1; time=0; Time=0; break; jtest=jtest->next; printf(\"\\n\"); void FIFU(freeBlock*free,jobQueue*job) {

int size=0,Time=0,time=0; jobQueue*jtest=job; freeBlock*ftest=free; while(ftest) {

} size++; ftest=ftest->next;

printf(\"FIFU置换页面为:\"); while(jtest) {

ftest=free; while(ftest) {

} ftest=free; while((time==size)&&ftest) {

if(check(free,jtest->index)) {

} if(ftest->time==Time) time=0; Time=0; break; if(ftest->index==-1) {

} ftest->time++; if(Timetime) Time=ftest->time; time++; ftest=ftest->next; ftest->index=jtest->index; ftest->time++; time=0; break;

}

}

} {

} ftest=ftest->next; printf(\"%d \",ftest->index); ftest->index=jtest->index; ftest->time=1; time=0; Time=0; break; jtest=jtest->next; printf(\"\\n\"); void main() {

int num,ch,p; freeBlock*block=NULL; jobQueue*job=NULL; printf(\"请输入物理块数目:\"); scanf(\"%d\",&p); for(int i=0;i } job=creat(job,ch); FIFU(block,job); LRU(block,job); while(true) {

printf(\"增加物理块(1)减少物理块(2),否则按任意键scanf(\"%d\",&num); if(num==1) {

} else if(num==2) {

printf(\"要减少几块:\"); scanf(\"%d\",&ch); if(ch>=p) {

} for(i=0;i

}

}

} FIFU(block,job); LRU(block,job); else ;break; 3.实验结果

4.实验结果分析

程序开始要输入物理块数目和作业个数,然后再输入作业.在测试后可以随意添加或删除物理块来测试算法的性能。

5 实验:磁盘调度算法——SCAN和SSTF 1.实验设计说明

算法定义了一个双向链表,利用双向链表可以很好的进行方向的转换,且双向链表的中有代表磁盘号的标识符index;两个算法均采用访问完一个磁盘序列时删除该序列,其中scan算法实现时有点麻烦,首先要找到当前磁盘号序列的Max最大值和最小值Min及指向他们的指针pmax,pmin,另外还要找到当前磁头的相邻的两个访问序列信息psmax,psmin;还有一个重要的标志,那就是访问的方向test;当遇到最大值或最小值时,便会反置test的值,也就是访问的方向

2.实验代码 #include #include #include typedef struct memory { int index; struct memory*left,*right; }memory; memory*creat() {

printf(\"请输入磁道队列以-1结束!\\n\"); int ch; memory*head=NULL,*tail,*p; scanf(\"%d\",&ch); while(ch!=-1) {

p=(memory*)malloc(sizeof(memory)); p->index=ch; p->left=p->right=NULL;

}

} if(!head) head=p; else {

} tail=p; scanf(\"%d\",&ch); tail->right=p; p->left=tail; return head; void SSTF(memory*head,int index) {

int index1=index,num; memory*p1=head,*p,*p2=NULL; while(true) {

num=abs(p1->index-index1); p=p1; while(p) {

} if((abs(p->index-index1))

} p=p->right; num=abs(p->index-index1); if(p!=p1) p2=p; p=p1->right; if(p2) {

} else { printf(\"%d \",p1->index); index1=p2->index; printf(\"%d \",p2->index); p2->left->right=p2->right; if(p2->right) p2->right->left=p2->left; free(p2); p2=NULL;

}

}

} index1=p1->index; if(!p) {

} else {

} p=p1; p1=p1->right; free(p); continue; free(p1); break; void SCAN(memory*head,int index) {

int index1=index,num,test,max=0,min=199,Max,Min; printf(\"请输入磁头查询方向!\\n\"); scanf(\"%d\",&test); memory*p1=head,*p,*p2=NULL,*pmax,*pmin,*psmax=NULL,*psmin=NULL;

while(p1) {

} p1=head; while(p1) { if(!test) { if(!test) {

} else {

} p1=p1->right; pmin=p1; if(p1->indexindex; pmax=p1; if(p1->index>=max) Max=max=p1->index;

}

} pmin=p1; if(p1->indexindex;

else {

} p1=p1->right; pmax=p1; if(p1->index>=max) Max=max=p1->index; p1=head; while(true) {

num=abs(p1->index-index1); p=p1; while(p) {

if(!test) { if(p->index>=index1&&p->index

}

}

if((abs(p->index-index1))

}

psmin=p;

num=abs(p->index-index1); if(p->left&&p->right) p2=p; else {

} p=p->right; if(p->indexindex>=min)

if(abs(p->index-index1)

}

psmax=p;

num=abs(p->index-index1); if(p->left&&p->right) p2=p; if(p2)

{

if(!test) {

} else {

index1=psmax->index; p=psmax; if(index1==Min) {

} test=0; Max=Min=-1; p1=pmin; index1=psmin->index; p=psmin; if(index1==Max) {

} test=1; Min=Max=-1; p1=pmax;

} printf(\"%d \",index1); if(!test) {

} else { if(psmax) if(psmin) {

} else {

} psmax->right->left=psmax->left; if(psmax->left)

psmax->left->right=psmax->right; psmin->left->right=psmin->right; if(psmin->right)

psmin->right->left=psmin->left; free(psmin); free(psmax);

}

} {

} else {

} psmin->right->left=psmin->left; if(psmin->left)

psmin->left->right=psmin->right; psmax->left->right=psmax->right; if(psmax->right)

psmax->right->left=psmax->left; free(psmax); free(psmin); else {

if(!test) {

if(p1->index==Max) { test=1;

} } Min=Max=-1; else {

} if(psmax) {

} else {

} printf(\"%d \",index1); index1=psmin->index; p=psmin; index1=psmax->index; p=psmax; if(p1->index==Min) {

} test=0; Max=Min=-1;

}

}

} if(p->left&&!p->right) {

} else if(p->right&&!p->left) {

} else if(!p->right&&!p->left) {

} free(p); free(p); break; p1=p->right; p1->left=NULL; p1=p->left; p1->right=NULL; p2=psmax=psmin=NULL; void main() {

int p,t; memory*head=creat(); printf(\"请输入磁头当前的位置(0-199)\"); scanf(\"%d\",&p); printf(\"要进行的算法:\"); scanf(\"%d\",&t); if(!t) SCAN(head,p); else SSTF(head,p); } 3.实验结果

4.实验结果分析

输入要访问的磁盘号,然后选择要实现的算法就可以看到结果,当选0(正向)的时候由于当前的磁头在143处,所以要访问的磁盘号就必须大于143,当最大的磁盘号访问完时,就转向小于143的磁盘开始由大向小访问,选1的话则相反。 最短寻道时间算法是从整个队列中选择距离磁头最近的访问,算法的实现运用了绝对值的概念

第20篇:《操作系统课程设计》内容要求

《操作系统课程设计》

注意事项:要求每个同学独立完成以下三个项目中的任两个,编程语言不限.

项目一:命令行解释程序

【教学内容】 利用C语言编写一个微型命令解释程序,体会操作系统作为用户与计算机接口的作用。巩固C语言编程能力。

1.所设计的微型命令解释程序具有下列5条命令  cdir (列出当前文件和目录)

 ccopy 文件1 文件2

(拷贝文件)  cerase 文件名 (删除文件)  Cdis 字符串

(显示该字符串)

 Cend (退出微型命令解释程序) 2.项目报告要求

 列出采用的数据结构并加以说明。

 打印一份源程序清单,并附加流程图与注释。

 分析Windows操作系统和Linux操作系统的命令解释程序的不同之处。

【教学重点及难点】

重点:命令解释程序的作用。 难点:命令解释程序的实现原理。

【基本要求】

 了解常用操作系统的命令操作方式和不同操作系统的命令解释程序。  理解命令解释程序的作用。  掌握命令解释程序的实现原理。

【主要实践教学条件】

 IBM 586以上微型计算机及其兼容机。

 Windows xp/2000 以上版本,Linux redhat9 以上版本。  TURBO C 2.0、VC++、其他高级语言或GCC编译器。

项目二:进程控制

【教学内容】 利用Linux进程控制部分的主要系统调用进行编程,实现对进程的创建、终止、同步和通信等控制,提高学生对进程控制系统调用的编程能力,加深对进程控制的理解。

1.实现对进程的如下控制操作  进程的创建和终止;  进程的状态转换;  进程之间的通信;  进程之间的互斥访问文件。 2.项目报告要求

 列出采用的数据结构并加以说明。

 打印一份源程序清单,并附加流程图与注释。

 分析Windows操作系统和Linux操作系统的进程控制系统调用的不同之处。

【教学重点及难点】

重点:进程之间的通信。 难点:进程之间的互斥。

【基本要求】

 了解常用操作系统的提供的常用进程控制类系统调用。  理解进程通信方式。  掌握用信号量实现进程互斥。

【主要实践教学条件】

 IBM 586以上微型计算机及其兼容机。

 Windows xp/2000 以上版本,Linux redhat9 以上版本。  TURBO C 2.0、VC++、其他高级语言或GCC编译器。

项目三:文件系统

【教学内容】模拟文件管理。设计并调试一个简单的文件系统,模拟文件操作命令的执行。深入了解主要文件操作命令的执行过程,掌握它们的基本实施方法。

1.实现文件系统的基本功能

 设计一个支持n个用户的文件系统,每个用户可拥有多个文件。  采用二级或二级以上的多级文件目录管理。

 对文件设置存取控制保护方式,如“只能执行”、“允许读”、“允许写”等。  系统的外部特征应接近于真实系统,可以设置下述文件操作命令:建立文件、打开文件、关闭文件、删除文件、读文件、写文件、复制文件、查询目录。  通过键盘使用该文件系统,系统应当显示操作命令的执行结果。 2.项目报告要求

 列出采用的数据结构及并加以说明。

 打印一份源程序清单,并附加流程图与注释。

 分析Windows操作系统和Linux操作系统的文件系统的不同之处。  分析Windows操作系统和Linux操作系统的文件操作命令有何不同。 【教学重点及难点】

重点:文件系统的主要功能。

难点:文件系统的常用命令的主要工作。

【基本要求】

 了解各种文件操作系统的异同。  理解常用操作系统支持的文件操作系统。  掌握文件系统的主要功能。

 掌握文件系统的常用命令的主要工作。

【主要实践教学条件】

 IBM 586以上微型计算机及其兼容机。

 Windows xp/2000 以上版本,Linux redhat9 以上版本。  TURBO C 2.0、VC++、其他高级语言或GCC编译器。

、必备教材、实践教学指导书和参考资料

(一)必备教材

1.《操作系统实验教程(Linux版)》,潘景昌 编著,清华大学出版社,2010年第1版。

(二)实践教学指导书

1.《计算机操作系统实验与实践——基于Windows与Linux》,秦明 编著,清华大学出版社,2010年第1版。

2.《操作系统实验教程及Linux和Windows系统调用编程》,张丽芬 编著,清华大学出版社,2010年第1版。

(三)参考资料

1.《操作系统原理实用教程》,李俭 编著,清华大学出版社,2011年第1版。

2.《操作系统原理实验教程(基于Linux)》,胡峰松 编著,清华大学出版社,2010年第1版。

3.《计算机操作系统》,汤小丹 编著,西安电子科技大学出版社,2007年第3版。

、课外学习要求

1.项目一命令解释程序课外学习要求

 了解Windows操作系统和Linux操作系统的命令解释程序,并分析二者的不同之处。

 会使用Windows操作系统和Linux操作系统的常用命令。  完成项目一的报告。 2.项目二进程控制课外学习要求

 了解Windows操作系统和Linux操作系统的进程控制类常用系统调用,并分析二者的不同之处。

 了解Windows操作系统和Linux操作系统中实现进程同步的系统调用方法有哪些,并能利用该方法够编程实现进程的同步。  完成项目二的报告。 3.项目三文件系统课外学习要求

 了解Windows操作系统和Linux操作系统的文件系统,并分析二者的不同之处。  会使用Windows操作系统和Linux操作系统的文件操作命令,分析两种操作系统支持的文件操作命令有何不同。  完成项目三的报告。

考核及成绩评定方式

1.考核方式

本课程设计中的三个项目都属于综合设计类项目,所以对每个项目进行验收时,通过学生演示程序实现的功能,检查学生完成的程序是否符合项目要求,结合源程序代码对学生进行质疑,每个项目有一个验收成绩。 2.成绩评定方式

总评成绩=课程设计报告(30%)+平时 (70%)。平时成绩包括考勤、提问、质疑和课程设计期间表现等,主要考查学生日常项目完成情况,注重对学生能力的考核。课程设计报告要符合要求并独立完成。

操作系统课程设计
《操作系统课程设计.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
相关专题
点击下载本文文档