广工 - 操作系统 - 实验介绍

更新时间:2023-12-31 04:08:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

操作系统实验报告

学 院_____计算机学院_______ 专 业______软件工程________ 班 级______ ________ 学 号_____ _______ 姓 名_______ _________ 指导教师

(2010年10 月)

学号: 姓名: 协作者:________

实验__一__题目__ 进程调度___第 周星期__ _

一、实验目的

用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理

解。

二、实验内容和要求

编写并调试一个模拟的进程调度程序,采用“轮转法”调度算法对五个进程进行调度。 ·每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、

优先数、到达时间、需要运行的时间、已用CPU时间、进程状态等。

·进程的优先数以及需要的运行时间事先由人为指定(也可以随机数产生)。 ·如果运行一个时间片后进程的已占用CPU时间已达到所需要的运行时间,则撤销该进

程,如果还未达到,则把它送回队尾。

三、实验主要仪器设备和材料

四、实验原理及设计方案 1、实验原理

将程序顺序的输入进程队列后,开始执行程序,当运行了一个时间片后,如果进程所占实验环境

硬件环境:IBM-PC 或兼容机 软件环境:C语言编程环境

的CPU时间达到所需的运行时间时,该进程完成,并撤销该进程,否则则把进程送回队尾。

2、设计方案

用一个进程控制块(PCB)表示进程。输入进程名称,优先级,运行时间后,通过模拟

系统对进程采用“轮转法”调度,得到各个时间片进程的运行情况。

3、相关数据结构的说明

struct pcb // 定义进程控制块 PCB {

char name[10]; // 进程名称 char state; int super; int ntime; int rtime;

// 进程当前状态 // 进程优先级 // 进程运行所需时间 // 进程已运行时间

struct pcb* link; // 连接到队列中下一个进程的指针 }

4、程序流程图(详细)

5、给出程序中源程序名和可执行程序名。

源程序名:pcb.cpp

6、程序清单(源程序中要附有详细的注释) #include

#define getpch(type) (type*)malloc(sizeof(type))

struct pcb // 定义进程控制块 PCB {

char name[10]; char state; int super; int ntime; int rtime;

// 进程名称 // 进程当前状态

可执行程序名:pcb.exe 输入数据:in.txt 输出数据:out.txt

// 进程优先级 // 进程运行所需时间 // 进程已运行时间

struct pcb* link; }*ready,*p,*rear;

typedef struct pcb PCB;

void push() { }

rear->link = p; rear = p; p->link = NULL;

// 建立将进程按 FCFS 排入队列的函数

p->state = 'w'; // 插入队尾后把状态改成'w'

void input() // 建立进程控制块函数 {

int i,num;

printf(\请输入进程数量 \scanf(\

}

p=getpch(PCB); // 给 p 分配空间 for( i=0; i< num; i++) { }

printf(\进程号 No.%d \p = getpch(PCB); printf(\输入进程名:\scanf(\

printf(\输入进程优先等级:\scanf(\

printf(\输入进程所需运行时间:\scanf(\

p->rtime = 0; // 为进程的已运行时间初始化为0 p->state = 'w'; // 为进程的状态初始化为 'w' p->link = NULL; push();

void disp(PCB* pr) // 建立进程显示函数 {

printf(\ printf(\ printf(\ printf(\ printf(\ printf(\ printf(\}

void check() // 建立进程查看函数 {

system(\ PCB *pr; pr=ready->link;

while(pr!=NULL) // 队列从头到尾显示进程 {

disp(pr); pr = pr->link; } }

void destroy() // 建立进程撤消函数 {

disp(p);

printf(\进程 [%s] 已完成。\\n\ free(p); // 释放 p }

void running() // 建立进程就绪函数 {

p->rtime++; // 已运行时间增加

if(p->rtime == p->ntime) // 当已运行时间等于所需运行时间时 {

p->state = 'f'; // 状态更新为'f' ready->link = p->link;

destroy(); // 调用destory()函数,释放p p = ready->link;

system(\ // 暂停,可了解当前状态 }

else // 如果进程还没达到所需运行时间,则把进程送入队尾 {

ready->link = p->link; push(); p = ready->link; } }

int main() // 主函数 {

int t=0; // 定义t表示已用的时间片 rear = getpch(PCB); // 为rear分配内存 ready = rear; // 把ready指向rear

input(); // 输入进程

p = ready->link;

check();

while(ready->link) // 当进程队列中还有进程时运行 {

t++;

p->state = 'r'; // 将进程状态设置为 ready

check();

printf(\第%d个时间片:\ printf(\正在运行\\n\

system(\ // 显示正在运行的进程队列 running(); check();

printf(\第%d个时间片:\ printf(\运行完成\\n\

system(\ // 显示运行完成后的进程队列 } }

五、实验结果及分析

1、运行结果(要求截图)(能动态说明执行结果)(要求截图尺寸大小适中)

(1)输入数据

printf(\全部进程已运行完成!\\n\system(\return 0;

(2)开始运行,进程队列如图

(3)经过3个时间片,进程【333】完成

(4)经过9个时间片,进程【555】完成

(5)经过10个时间片,进程【111】完成

(6)经过12个时间片,进程【444】完成

(7)经过13个时间片,进程【222】完成

(8)全部进程运行完成

2、实验结果的分析及说明

程序输出与编写程序的目的一致,直观的反应了轮转法进程调度的运行规则,显示了完

成各个进程运行所需要的时间,以及各个进程完成的顺序。

六、调试总结及心得体会

(调试过程中小结、所遇问题及解决方法、心得体会)

整个调试过程中并未遇到太大的问题,程序编写过程也很顺利,运行程序模拟进程调度

之后,更直观的了解了轮转法进程调度的过程。

七、思考题

1、 分析不同调度算法的调度策略,比较不同调度算法的优缺点,总结它们的适用范围。 答:动态有限权算法:动态优先权是指在创建进程时所创建的优先权,会随进程的推进或者等待时间的增加而改变,以便获得更好的调度性能。处理机为每个进程分配一定的时间片,在就绪队列中,优先权高的进程将优先获得处理机,进程在进去运行完响应的时间片后,如没完成,优先权减1,从新回到就绪队列等待分配处理机。

时间片的轮转法:系统将所有进程排成一个队列,按照先来先服务的原则,对队列首的进程进行处理,每个进程在用完自己的时间片后,从新回到队尾进行排队。每运行一次,进程的需要时间减1,直到就绪队列为空!

学号: 姓名: 协作者:________

实验__二__题目__ 作业调度___第 周星期__ _

一、实验目的

本实验要求学生模拟作业调度的实现,用高级语言编写和调试一个或多个作业调度的模拟程序,了解作业调度在操作系统中的作用,以加深对作业调度算法的理解。

二、实验内容和要求

作业调度算法:采用基于先来先服务的调度算法。可以参考课本中的方法进行设计。 对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个 作业的资源要求。

三、实验主要仪器设备和材料

硬件环境:IBM-PC或兼容机 软件环境:C语言编程环境

四、实验原理及设计方案 1、实验原理

采用多道程序设计方法的操作系统,在系统中要经常保留多个运行的作业,以提高系统效率。作业调度从系统已接纳的暂存在输入井中的一批作业中挑选出若干个可运行的作业,并为这些被选中的作业分配所需的系统资源。对被选中运行的作业必须按照它们各自的作业说明书规定的步骤进行控制。

2、设计方案

(1)作业调度程序负责从输入井选择若干个作业进入主存,为它们分配必要的资源,

当它们能够被进程调度选中时,就可占用处理器运行。作业调度选择一个作业的必要条件是系统中现有的尚未分配的资源可满足该作业的资源要求。但有时系统中现有的尚未分配的资源既可满足某个作业的要求也可满足其它一些作业的要求,那么,作业调度必须按一定的算法在这些作业中作出选择。先来先服务算法是按照作业进入输入井的先后次序来挑选作业,先进入输入井的作业优先被挑选,当系统中现有的尚未分配的资源不能满足先进入输入井的作业时,那么顺序挑选后面的作业。

(2) 假定某系统可供用户使用的主存空间共100k,并有5台磁带机。

3、相关数据结构的说明

struct time { int h; int m;

}t; struct jcb {

};

4、程序流程图(详细)

char name[10];

// 作业名称

// 定义一个作业结构已

// 定义一个时间结构体

struct time submittime; // 提交时间 struct time starttime; // 开始时间 struct time needtime; // 需要运行的时间 struct time finishtime; // 完成时间 char state;

// 状态

// 连接到下一个作业的指针

struct jcb* link;

5、给出程序中源程序名和可执行程序名。

源程序名:jcb.cpp

6、程序清单(源程序中要附有详细的注释) #include #include

#define getpch(type) (type*)malloc(sizeof(type))

可执行程序名:jcb.exe 输入数据:in.txt 输出数据:out.txt

struct time {

int h; int m; }t;

struct jcb {

// 定义一个时间结构体

// 定义一个作业结构已

char name[10]; // 作业名称

struct time submittime; // 提交时间 struct time starttime; // 开始时间 struct time needtime; // 需要运行的时间 struct time finishtime; // 完成时间 char state;

// 状态

// 连接到下一个作业的指针

struct jcb* link; }*ready,*p,*rear;

typedef struct jcb JCB; int num;

void push() { }

rear->link = p; rear = p;

// 建立将进程按 FCFS 排入队列的函数

void disp(JCB* pr) // 建立作业显示函数 {

printf(\ name\\tstate\\tsubmittime\\tneedtime\\tstarttime\\tfinishtime\\ttime \\n\

printf(\ printf(\

printf(\ printf(\ printf(\

printf(\

printf(\ittime.m); printf(\}

void input() {

int i;

printf(\请输入作业数量 \scanf(\

p=getpch(JCB); // 给 p 分配空间 for( i=0; i< num; i++) {

p = getpch(JCB); printf(\输入作业名:\scanf(\

printf(\输入作业提交时间(h:m):\

scanf(\printf(\输入作业所需运行时间(h:m):\scanf(\printf(\

p->state = 'w'; // 为作业的状态初始化为 'w' p->link = NULL;

// 建立作业控制块函数

push(); p = NULL; }

void running() // 建立作业就绪函数 {

if(p->submittime.h < t.h||(p->submittime.h == t.h && p->submittime.m <= t.m)) {

p->starttime.h=t.h; p->starttime.m=t.m;

// 当提交时有程序在运行

// 则开始时间等于上一程序运行完成时间

}

} else {

// 否则开始时间等于提交时间

t.h=p->submittime.h; t.m=p->submittime.m; p->starttime.h=t.h; p->starttime.m=t.m; }

t.h=p->needtime.h+t.h; t.m=p->needtime.m+t.m; if(t.m>=60) {

t.h++; t.m-=60; }

p->finishtime.h=t.h; p->finishtime.m=t.m; p->state='f'; push(); }

int main() // 主函数 {

//freopen(\ //freopen(\ int i;

rear = getpch(JCB); ready = getpch(JCB); rear = ready; input(); p=ready->link; t.h=p->submittime.h; t.m=p->submittime.m; printf(\ for(i=0;i

running(); disp(p); p = p->link; }

p=ready->link; system(\ return 0; }

五、实验结果及分析

1、运行结果(要求截图)(能动态说明执行结果)(要求截图尺寸大小适中)

输入数据:

输出结果:

2、实验结果的分析及说明

六、调试总结及心得体会

(调试过程中小结、所遇问题及解决方法、心得体会)

有了第一个实验的基础,在这个实验中,除了在处理小时与分钟的转换上花费了点时间之外,其余的部分都完成的比较顺利。

七、思考题

1、 写出每种算法的调度策略,最后比较各种算法的优缺点。

答:先来先服务算法是根据作业的进入时间来排序,到达时间短的先运行,优点是实现简单,缺点是运行时间慢。

短作业优先算法是根椐作业的估计运行时间来排序,估计运行时间短的先运行,优点是运行时间快,缺点是实现起来比较复杂。

2、 选择调度算法的依据是什么?

答:如果作业要求的速度不高,而且作业比较小型,那就最好用先来先服务算法。

如果作业要求的速度高,作业流程复杂,那就最好用短作业优先算法。

根据实验输入,输出了运行后各个作业的开始时间,完成时间以及周转时间。

学号: 姓名: 协作者:________

实验__四__题目 主存空间的分配和回收_第 周星期__

一、实验目的

熟悉主存的分配与回收。理解在不同的存储管理方式下,如何实现主存空间的分配与回收。掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方式及其实现过程。

二、实验内容和要求

主存的分配和回收的实现是与主存储器的管理方式有关的。所谓分配,就是解决多道作业或多进程如何共享主存空间的问题。所谓回收,就是当作业运行完成时将作业或进程所占的主存空间归还给系统。

可变分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需求,并且分区个数是可以调整的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入,作业等待。随着作业的装入、完成,主存空间被分成许多大大小小的分区,有的分区被作业占用,而有的分区是空闲的。

实验要求使用可变分区存储管理方式,分区分配中所用的数据结构采用空闲分区表和空闲分区链来进行,分区分配中所用的算法采用首次适应算法、循环首次适应算法、最佳适应算法三种算法来实现主存的分配与回收。同时,要求设计一个实用友好的用户界面,并显示分配与回收的过程。

三、实验主要仪器设备和材料

硬件环境:IBM-PC或兼容机 软件环境:VC++ 6.0

四、实验原理及设计方案

1、实验原理

在该算法中,把主存中所有空闲区按其物理地址递增的次序排列。在为作业分配存储空间时,从上次找到的空闲分区的下一个空闲分区开始查找,直到找到第一个能满足要求的空闲区,从中划出与请求的大小相等的存储空间分配给作业,余下的空闲区仍留在空闲区表或链中。

2、设计方案

(1)初始化空闲分区;

(2)反复对现有的空闲分区进行进程创建和撤消,即内存分配和回收;

(3)退出。

3、相关数据结构的说明 struct zone {

int size; // 区域的大小 int state; // 区域的状态 char name[10]; // 区域的名称

struct zone *link; // 连接到下一区域的指针 };

4、程序流程图(详细)

5、给出程序中源程序名和可执行程序名。

源程序名:memory.cpp

可执行程序名:memory.exe 输入数据:in.txt

输出数据:out.txt

6、程序清单(源程序中要附有详细的注释) #include #include #define MAX 5

struct page // 定义一个页表 page {

int num; // 页号 char imformation[100]; // 页表信息

page * next; // 指向下一个页表的指针

}*address,*memory; // 定义一个指令地址指针和主存指针

void print(page *pp) // 输出页表 {

printf(\

printf(\}

void AddToAddress() // 向指令地址添加页表 {

int a; page *p,*pp; p = address; while(1) {

printf(\ scanf(\ if(a) {

pp = (page *)malloc(sizeof(page)); // 分配内存空间 pp->num = a;

printf(\ scanf(\

pp->next = NULL;

p->next = pp; // 把页表连接到address后 p = pp; print(p); pp = NULL; free(pp); } else {

return; } } }

void init() // 初始化程序,为address和memory分配内存空间 {

address = (page *)malloc(sizeof(page)); memory = (page *)malloc(sizeof(page)); AddToAddress(); }

bool IsInMemory(int n) // 判断页号是否已在主存内 {

page * p; p = memory->next; while(NULL != p) {

if(p->num == n) {

printf(\ return 1; } p = p->next; }

printf(\ return 0;

}

bool IsMemoryFull() // 判断主存是否已满 {

page *p; int i = 0; p = memory->next; while(NULL != p) { i++; p = p->next; }

if(i >= MAX) // 主存中页表的数量达到 MAX 时,主存已满 {

printf(\ return 1; } else {

printf(\ return 0; } }

void DeletePage() // 用 FIFO 算法淘汰一页 {

page *p; p = memory; memory = p->next; free(p); }

void AddToMemory(page *pp) // 向主存调入当前页表 {

page *p; p = memory;

while(NULL != p->next) {

p = p->next; } p->next = pp; }

int main() {

init(); //初始化 page * p; page * pp; p = address; p = p->next; while(p) {

if(!IsInMemory(p->num)) // {

if(IsMemoryFull()) // {

DeletePage(); // } printf(\

AddToMemory(p); // } print(p); pp = p; p = p->next; pp->next = NULL; }

printf(\ p = memory->next; while(p) {

print(p); p = p->next;

判断 p 是否已在主存内判断 主存是否已满 用 FIFO 算法淘汰一页 向主存调入当前页表 打印当前主存区内情况

}

system(\}五、实验结果及分析

1、运行结果(要求截图)(能动态说明执行结果)(要求截图尺寸大小适中)

输入命令:task1 new 130

输入命令:task2 new 60

输入命令:task3 new 100

输入命令:task2 delete 60

输入命令:task4 new 200

输入命令:task3 delete 100

输入命令:task1 delete 130

输入命令:task5 new 140

输入命令:task6 new 60

输入命令:task7 new 50

输入命令:task 3 new 50 (错误的命令)

输入命令:quit 结束

2、实验结果的分析及说明

本实验用了一条链表将所有的内存都连接起来,在之中按照书上要求的算法,分别执行

了每一条命令,结果完全正确,对错误的命令也能够及时的判断出来。

六、调试总结及心得体会

(调试过程中小结、所遇问题及解决方法、心得体会)

通过前几个实验,对链表又有了深刻的了解,所以在这个对链表操作更为复杂的实验中,

感觉游刃有余,对内存空间的开辟以及释放有了更深刻的了解,整个程序在编写的过程中也没有碰到太大的困难,最主要是在编写之前已经深刻的把整个构思在大脑中了。

七、思考题

1、内存的主要分配方式有哪些?回收时可能出现的什么情况?应怎样处理这些情况? 答:有定分区分配和动态分区分配两种,回收时可能出现内存分区被切成若干在小不等小分

区,过小的分区浪费内存资源,这要求我们要用紧凑技术修整。

2、动态分区管理的常用内存分配算法有哪几种?比较它们各自的使用范围。 答:有首次适应算法、循环首次适应算法、最佳适应算法三种。

首次适应算法适用于小型作业,而且分配速度不怎么要求的作业,循环首次适应算法适用于一些大的作业,避免大作业长期得不到分配,最佳适应算法适应于对分配速度要求高,作业容量比较大的作业。

学号: 姓名: 协作者:________

实验__五__题目__ 文件系统___第 周星期__ _

一、实验目的

模拟文件系统实现的基本功能,了解文件系统的基本结构和文件的各种管理方法,加深理解文件系统的内部功能及内部实现。通过用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。

二、实验内容和要求

编程模拟一个简单的文件系统,实现文件系统的管理和控制功能。要求本文件系统采用两级目录,即设置主文件目录[MFD]和用户文件目录[UED]。另外,为打开文件设置运行文件目录[AFD]。设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件,并对文件必须设置保护措施。在用户程序中通过使用文件系统提供的Create、open、read、write、close、delete等文件命令,对文件进行操作

三、实验主要仪器设备和材料

硬件环境:IBM-PC或兼容机 软件环境:C语言编程环境

四、实验原理及设计方案

1、实验原理

运用二级目录思想来模拟文件系统。

为每个用户建立一个单独的用户文件目录UFD。这些文件目录具有相似的结构,它由 用户文件的文件块组成。此外,在系统再建立一个主文件目录MFD;在主文件目录中,每个用户目录都占有一个目录项,其目录项中包含文件名和指向该文件目录文件的指针。

2、设计方案

按照课本要求,为每一个命令设置一个函数,再由主界面接受命令,进行判断以及调用

函数。

3、相关数据结构的说明 struct MDF {

char username[200];

// username

// 定义一个用来存放user和ufd的结构体

int length; struct UFD *userufd; struct MDF *link; }*mdfhead,*mdfptr;

struct UFD

{

char filename[200]; int num;

int length;

struct UFD *link;

}*ufdptr;

struct AFD

{

char username[200]; char filename[200]; int num;

int state; int length;

struct AFD *link; }*afdhead,*afdptr;

4、程序流程图(详细)

// user 文件目录长度 // 指向user文件目录的指针 // 指向下一个user的指针 // 头指针

// 定义用来存放files的链表

// filename // 保护码 // file长度

// 指向下一个file的指针

// 定义一个用来存放已经打开的files的链表// username // filename // 保护码 // 读写指针 // file长度

// 指向下一个file的指针 // 头指针

5、给出程序中源程序名和可执行程序名。

6、程序清单(源程序中要附有详细的注释) #include #include #include

struct MDF {

char username[200];

// username

// 定义一个用来存放user和ufd的结构体

源程序名:file.cpp 可执行程序名:file.exe

int length;

// user 文件目录长度 // 指向user文件目录的指针 // 指向下一个user的指针 // 头指针

struct UFD *userufd; struct MDF *link;

}*mdfhead,*mdfptr;

struct UFD {

// 定义用来存放files的链表

char filename[200]; int num;

// filename // 保护码 // file长度

// 指向下一个file的指针

int length;

struct UFD *link;

}*ufdptr;

struct AFD {

char username[200]; char filename[200]; int num;

// username // filename // 保护码 // 读写指针 // file长度

// 指向下一个file的指针 // 头指针

// 定义一个用来存放已经打开的files的链表

int state; int length;

struct AFD *link;

}*afdhead,*afdptr;

void init();

bool createfile(char* username,char* filename,int num); bool deletefile(char * username,char * filename); bool openfile(char * username,char * filename); bool closefile(char * username,char * filename); bool readfile(char * username,char * filename); bool writefile(char * username,char * filename);

void init() {

afdhead = (AFD *)malloc(sizeof(AFD)); afdhead->link = NULL; afdhead->length = 0;

// 为afdhead分配空间,

// 初始化函数

并link = null,length = 0 afdptr = afdhead; int i = 10;

mdfhead = (MDF *)malloc(sizeof(MDF)); mdfptr = mdfhead;

struct MDF *mp; struct UFD *up; char str[200]; while(i--)

{

mp = (MDF *)malloc(sizeof(MDF));

并link = null

sprintf(str,\ strcpy(mp->username,str);

mp->length = 0;

up = (UFD *)malloc(sizeof(UFD));

ufd,并link = null,length = 0 mp->userufd = up; mp->userufd->length = 0; mp->userufd->link = NULL; mp->link = NULL; mdfptr->link = mp; mdfptr = mp; up = NULL; mp = NULL;

}

}

bool createfile(char* username,char* filename,int num) {

bool flag = false;

flag用来做返回值 mdfptr = mdfhead->link; struct UFD *up;

while(mdfptr)

找username

// 为mdfhead分配空间

// 初始化10个用户名

// 为每个user分配空间,

// 从user1到user10

// 为每个user分配一个

// create函数

// 定义一个bool类型的

// 从第一个user开始寻

{

if(!strcmp(mdfptr->username,username)) {

if(mdfptr->length >=10)

// 如果user保存文件数

// 找到username之后

超过10个,则提示错误并返回 { printf(\ return flag;

}

ufdptr = mdfptr->userufd; up = ufdptr->link;

while(up)

filename {

if(!strcmp(up->filename,filename)) 并返回 { printf(\ return flag;

}

up = up->link; ufdptr = ufdptr->link;

}

up = (UFD *)malloc(sizeof(UFD)); strcpy(up->filename,filename); up->length = 0;

up->num = num; up->link = NULL; ufdptr->link = up; mdfptr->length++;

printf(\ flag = true; return flag;

}

mdfptr = mdfptr->link;

}

// 在user的ufd中查找

// 如果重复,则提示错误

// 正常创建文件,分配空间 // 复制用户名和文件名

// 文件长度默认为0

// user的ufd长度加1

// 正确返回

printf(\ // 不存在username,提示

错误并返回 }

bool deletefile(char * username,char * filename) {

bool flag = false;

// 定义一个bool类型的

// delete函数

return flag;

flag用来做返回值

mdfptr = mdfhead; struct UFD *up; while(mdfptr) {

if(!strcmp(mdfptr->username,username)) {

ufdptr = mdfptr->userufd; up = ufdptr->link; while(up) { }

printf(\

// 不存在filename,提示

if(!strcmp(up->filename,filename)) { }

ufdptr = up; up = up->link;

closefile(username,filename); ufdptr->link = up->link; free(up);

// 释放空间 // mdf文件个数减1

// close file // 查找filename

// 查找username

mdfptr->length--;

printf(\flag = true; return flag;

错误并返回

flag = false; return false;

}

}

mdfptr = mdfptr->link;

printf(\ // 不存在username,提示

错误并返回 }

bool openfile(char * username,char * filename) {

bool flag = false;

// 定义一个bool类型的

// openfile函数

flag = false; return flag;

flag用来做返回值

struct AFD *ap; afdptr = afdhead; ap = afdptr->link; if(afdhead->length >= 5)

// 打开文件超过5个,提

示错误并返回

{ }

mdfptr = mdfhead; while(mdfptr->link) {

if(!strcmp(mdfptr->username,username)) {

ufdptr = mdfptr->userufd; while(ufdptr)

// 找到username后

// 寻找username

printf(\return flag;

// 从user的ufd中开始查找

filename

{

if(!strcmp(ufdptr->filename,filename)) {

while(ap)

// 查找afd已打开的文件中是否有

重复

{

if(!strcmp(ap->filename,filename)&&!strcmp(ap->username,username))

}

ap = (AFD *)malloc(sizeof(AFD));

// 正常open file,分配

{ }

afdptr = afdptr->link; ap = ap->link;

printf(\flag = false; return flag;

空间

}

printf(\

// 如果在user中找不到

}

ufdptr = ufdptr->link;

strcpy(ap->filename,filename); strcpy(ap->username,username); ap->link = NULL; ap->num = ufdptr->num; ap->state = 0; afdptr->link = ap; afdhead->length++; afdptr = ap; ap = NULL;

printf(\flag = true; return flag;

// 正常返回

// afd的长度加1

// 复制文件名和保护码

// 默认读指针 = 0

该文件,提示错误并返回

}

printf(\

// 如果找不到username,

}

mdfptr = mdfptr->link;

flag = false; return flag;

提示错误并返回

}

flag = false; return flag;

bool closefile(char * username,char * filename) {

bool flag; struct AFD * ap; ap = afdhead->link; afdptr = afdhead; while(ap) {

// closefile函数

// 在afd中查找

if(!strcmp(ap->username,username)&&!strcmp(ap->filename,filename)) {

afdptr->link = ap->link;

// username和filename

都相同时close }

bool readfile(char * username,char * filename) { }

bool writefile(char * username,char * filename)

// writefile函数

return(openfile(username,filename));

// readfile函数

}

printf(\flag = false; return flag;

// 提示错误并返回

}

afdptr = ap; ap = ap->link;

free(ap);

afdhead->length--;

printf(\flag = true; return flag;

{ }

void disp() { }

mdfptr = mdfhead->link;

printf(\while(mdfptr) { }

printf(\afdptr = afdhead->link; while(afdptr) { }

printf(\afdptr = afdptr->link;

// 显示已经打开了的文件

printf(%ufdptr = mdfptr->userufd->link; if(!ufdptr) { }

while(ufdptr) { }

mdfptr = mdfptr->link;

printf(%ufdptr = ufdptr->link; printf(\

// 显示各用户名下的文件

// 显示files函数

if(openfile(username,filename)) { }

return false;

afdptr->state = 1; return true;

int main() {

init(); char com[100]; char username[200]; char filename[200];

int num;

bool flag = false; while(1) {

printf(\

//

对系统的介绍

printf(\printf(\

printf(\file:create [username] [filename] [num(1read 2write

3run)]\\n\

scanf(\

if(!strcmp(com,\

//

printf(\

printf(\printf(\printf(\printf(\printf(\printf(\

printf(\disp(); printf(\

判断输入的命令

{

scanf(\scanf(\

scanf(\

}

else if(!strcmp(com,\{ }

else if(!strcmp(com,\{ }

else if(!strcmp(com,\{ }

else if(!strcmp(com,\{ }

else if(!strcmp(com,\{ }

else if(!strcmp(com,\{

flag = true;

scanf(\scanf(\writefile(username,filename); scanf(\scanf(\readfile(username,filename); scanf(\scanf(\closefile(username,filename); scanf(\scanf(\openfile(username,filename); scanf(\scanf(\

deletefile(username,filename); createfile(username,filename,num);

}

}

break;

else { }

system(\system(\

printf(\

}

if(flag) { }

break;

五、实验结果及分析

1、运行结果(要求截图)(能动态说明执行结果)(要求截图尺寸大小适中)

执行后的欢迎界面:有对各个命令的简单提示,以及介绍了系统中已有的用户名。system

state显示了系统的现状,openfile显示了已经打开的文件。 输入命令:create user1 file1 1

再次输入:create user1 file1 1 则会提示:

输入一下命令:create user1 file2 1

create user2 file1 1 create user6 file6 2 create user7 file3 1后

create user1 file3 1 create user4 file4 1 create user7 file7 1

输入open命令:open user4 file4

输入错误的open命令:open user file

和 open user1 file

open user1 file1

继续输入: open user1 file1

open user7 file3

open user1 file3 open user7 file7

再次输入:open user1 file2

则提示错误

输入close命令:close user1 file3和 输入错误的close命令时:close user file

输入write命令:write user1 file1

和错误的 write user file

输入read命令:read user7 file7

输入delete命令:delete user1 file1 (执行delete命令会先closefile)

输入quit命令:退出程序

2、实验结果的分析及说明

根据书上的要求,为文件系统写了6个命令,create,delete,open,close,write,read,

并分别为错误的输入判断并提示返回,正确并执行,执行后的状态也及时的反馈给使用者。 六、调试总结及心得体会

(调试过程中小结、所遇问题及解决方法、心得体会)

该实验感觉原理很简单,但做起来其实挺复杂,代码量也比之前的所有实验多的多,尽

管编程之前已经考虑了很久,感觉已经遍布了各种情况,但是在实际编程的时候,还是更改了几次结构体以及函数参数和变量,程序可以算的上是比较安全健壮了,考虑了许多的不合法输入,对每一种不合法输入都有反馈信息给用户,每一次成功输入也有提示输入成功,虽然在读指针和写指针并没有完全的完成,但也完成了课本上的要求,这个实验也教会了我系统化的构思一个小型系统的方法。

七、思考题

1、文件系统要解决哪些问题?

答:要解决文件和用户是否同名,文件创建数是否超额,所要求文件是否存在等问题。

2、什么是文件目录?什么是文件目录中包含哪些信息?目前广泛采用的目录结构形式是哪种?

答:文件目录就是用来展示一个用户的所有文件的一个表格,文件目录应包含文件名,保密码,文件大小,目前广泛采用的目录结构形式是多级目录形式。

输入quit命令:退出程序

2、实验结果的分析及说明

根据书上的要求,为文件系统写了6个命令,create,delete,open,close,write,read,

并分别为错误的输入判断并提示返回,正确并执行,执行后的状态也及时的反馈给使用者。 六、调试总结及心得体会

(调试过程中小结、所遇问题及解决方法、心得体会)

该实验感觉原理很简单,但做起来其实挺复杂,代码量也比之前的所有实验多的多,尽

管编程之前已经考虑了很久,感觉已经遍布了各种情况,但是在实际编程的时候,还是更改了几次结构体以及函数参数和变量,程序可以算的上是比较安全健壮了,考虑了许多的不合法输入,对每一种不合法输入都有反馈信息给用户,每一次成功输入也有提示输入成功,虽然在读指针和写指针并没有完全的完成,但也完成了课本上的要求,这个实验也教会了我系统化的构思一个小型系统的方法。

七、思考题

1、文件系统要解决哪些问题?

答:要解决文件和用户是否同名,文件创建数是否超额,所要求文件是否存在等问题。

2、什么是文件目录?什么是文件目录中包含哪些信息?目前广泛采用的目录结构形式是哪种?

答:文件目录就是用来展示一个用户的所有文件的一个表格,文件目录应包含文件名,保密码,文件大小,目前广泛采用的目录结构形式是多级目录形式。

本文来源:https://www.bwwdw.com/article/j5mx.html

Top