空闲磁盘存储空间的管理:位示图法
用位示图管理磁盘空间的分配与回收设计报告
课程设计报告( 2009--2010年度第二学期)课程名称:操作系统实验课设题目: 用位示图管理磁盘空间的分配与回收院系:控制与计算机工程学院班级:姓名:指导教师:李为设计周数: 一周成绩:2010年7月9 日一、需求分析要求打印或显示程序运行前和运行后的位示图,以及分配和回收磁盘的物理地址过程。
(1)假定现有一个磁盘组,共40个柱面。
每个柱面4个磁道,每个磁道又划分成4个物理记录。
磁盘的空间使用情况用位示图表示。
位示图用若干个字构成,每一位对应一个磁盘块。
1表示占用,0表示空闲。
为了简单,假定字长为16位,其位示图如图9—1所示。
系统设一个变量S,记录磁盘的空闲块个数。
(2)申请一个磁盘块时,由磁盘块分配程序查位示图,找出一个为0的位,并计算磁盘的物理地址(即求出柱面号、磁道号(也即磁头号)和扇区号)。
由位示图计算磁盘的相对块号的公式如下:相对块号一字号×16+位号之后再将相对块号转换成磁盘的物理地址:由于一个柱面包含的扇区数=每柱面的磁道数×每磁道的扇区数=4×4=16,故柱面号=相对块号/16的商,即柱面号=字号磁道号=(相对块号/16的余数)/4的商,即(位号/4)的商物理块号=(相对块号/16的余数)/4的余数,即(位号/4)的余数(3)当释放一个相对物理块时,运行回收程序,计算该块在位示图中的位置,再把相应位置0。
计算公式如下:先由磁盘地址计算相对块号:相对块号=柱面号×16+磁道号×4+物理块号再计算字号和位号:字号=相对块号/16的商,也即字号=柱面号位号=磁道号×物理块数/每磁道+物理块号(4)按照用户要求,申请分配一系列磁盘块,运行分配程序,完成分配。
然后将分配的相对块号返回用户,并将相对块号转换成磁盘绝对地址,再显示系统各表和用户已分配的情况。
(5)设计一个回收算法,将上述已分配给用户的各盘块释放。
并显示系统各表。
空闲磁盘存储空间的管理:位示图法
空闲磁盘存储空间的管理:位示图法空闲磁盘存储的管理:位示图法1:建立相应的数据结构2:磁盘上建立一个文件,文件长度设为10MB,为该文件来模拟一个磁盘,磁盘的物理块大小为512字节3:显示每次磁盘的请求和空间释放后的位示图状态4显示每次磁盘的请求和空间释放后的全磁盘的状态5:模拟文件的创建和删除,从而产生磁盘潘快请求和释放,验证以上设计代码:// OS暑?期ú课?程ì设Θ?计?.cpp : 定¨义?控?制??应畖用?程ì序ò的?入?口ú点?。
£//#include"stdafx.h"#include#include#includeusing namespace std ;//文?件t类え?class file{public:string name ;int occupy ;int grade_block ;int start ;};#define MAX_LINE 3#define MAX_COLUMN 32int BIT[32][1000];int byte[MAX_LINE] ;int file_count;int judge[32] ;int judge2[32];int cycle ;file f[1000];void init(int line ,int column);void show() ;void set(int now_location, int occupy );void clear(int now_location, int occupy);void bitset(int index ,int temp_block_quantity);void create_file(string temp_name, int temp_occupy );void delete_file(string name);bool byte_judge(int num,int i);int _tmain(int argc, _TCHAR* argv[]){string cmd;string file_name ;int file_occupy ;init( MAX_LINE, MAX_COLUMN ) ; //初?始?化ˉwhile ( cin >> cmd ) //{if( "q" == cmd || "Q" == cmd ){exit(0) ;return 0 ;}cin >> file_name ;if("create" == cmd){cin >>file_occupy ;create_file(file_name,file_occupy);}else{delete_file(file_name) ;}}return 0;}void show(){for(int i = 0 ; i < MAX_LINE ; i ++){for(int j = 0 ; j < MAX_COLUMN ; j ++){//cout<cout<<byte_judge(byte[i],j)<<" ";<="" p=""> }cout<< endl ;}}void set(int now_location, int occupy ){int line ;int column ;for(int i = 0 ; i < occupy ; i ++ ){line = (now_location - i) / MAX_COLUMN ;column = (now_location - i ) % MAX_COLUMN ; //BIT[line][column] = 1 ;byte[line] |= judge[column];}}//清?零?void clear(int now_location, int occupy){int line ;int column ;for(int i = 0 ; i < occupy ; i ++){line = (now_location + i) / MAX_COLUMN ; column = (now_location + i ) % MAX_COLUMN ; //BIT[line][column] = 0 ;byte[line] &= judge2[column];}}void bitset(int index ,int temp_block_quantity) {int block_quantity = temp_block_quantity ;int free_quantity = 0 ;int line, column ;int sign = cycle - 1 ;for (;; cycle++ ){line = cycle / MAX_COLUMN ;column = cycle % MAX_COLUMN ;if( 0 == byte_judge(byte[line],column)){free_quantity ++ ;}else{free_quantity = 0 ;}if(free_quantity >= block_quantity ){f[index].start = cycle - block_quantity + 1;set(cycle, block_quantity);cycle ++;cout<<"create file success"<<endl;< p="">show();return ;}if(cycle >= MAX_LINE * MAX_COLUMN-1){cycle = -1;free_quantity = 0;}if(sign == cycle ){break ;}}cout<<"error: create file fail"<<endl;< p="">}void create_file(string temp_name, int temp_occupy ) {int block_quantity ;f[file_count].name = temp_name ;block_quantity = temp_occupy / 512 + 1 ;f[file_count].occupy=block_quantity ;bitset(file_count ,block_quantity );file_count ++ ;}//删?除y文?件tvoid delete_file(string name){for(int i = 0 ; i < file_count ; i ++){if(name == f[i].name){clear(f[i].start,f[i].occupy);for(int j = i; j < file_count - 1; j ++){f[j] = f[ j + 1 ];}file_count -- ;cout<<"delete file success"<<endl;< p=""> show();return ;}}cout<<"ERROR THE FILE NOT EXIST"<< endl ; }//初?始?化ˉvoid init(int line ,int column){int con = 1 ;file_count = 0 ;cycle = 0 ;for(int i = 0; i < 32 ; i ++) {judge[i] = con ;judge2[i]=judge[i];judge2[i] ^= 0xffffffff;con*=2;}for(int i =0 ; i<="" p=""> byte[i]= 0;}bool byte_judge(int num,int i) {bool result ;result = num & judge[i]; return result;}</endl;<></endl;<></endl;<></byte_judge(byte[i],j)<<">。
位示图
实验名称:____________________________成绩:___________
专业班级:________姓名:_____ _____学号:0709014137
实验日期:年月日
实验报告日期:年月日
一、实验目的:实现位示图对文件存储空的管理
二、实验内容
在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简单的单用户文件系统。在退出这个简单的文件系统时,应将该虚拟文件系统保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中。2.文件存储空间的分配可采用显式链接分配或其他的办法。3.空闲空间的管理可选择位示图或其他的办法。。#include
这种方法是在外存上建立一张位示图(bitmap),记录文件存储器的使用情况。每一位仅对应文件存储器上的一个物理块,取值0和1分别表示空闲和占用。文件存储器上的物理块依次编号为:0、1、2、…。
位示图是利用二进制的一位来表示磁盘中一个盘块的使用情况。当其值为“0”时,表示对应的盘块空闲;为“1”时表示已分配。由所有盘块对应的位构成一个集合,称为位示图。位示图也可描述为一个二维数组map:Var map:array[1...m,1...n]of bit;
·修改位示图,令map[i,j]=1。
盘块的回收
盘块的回收分两步:
·将回收盘块的盘块号转换成位于图中的行号和列号。转换公式为:
i=(b-1)DIVn+1
j=(b-1)MODn+1
·修改位示图。令map[i,j]=0。
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
文件管理-空闲存储空间的管理
⽂件管理-空闲存储空间的管理
空闲存储空间管理:在磁盘上会有⼤量的空闲的空间,我们要将这些空闲的空间管理起来,以便在某个⽂件在申请相应空间的时候,能够有依据的分配他空间.
主要分为这⼏种办法:
空闲区表法:使⽤⼀个表来记录哪些空间是空闲的,以便来将这些空间管理起来
空闲链表法:将这些空闲的区域链成⼀条链表,当想要进⾏空间分配的时候,从这条链表之划出需要的空间来.
位⽰图法:表中 1表达该空间被占⽤了,⽽0表⽰该空间是空闲的,就像电影院选座⼀样.
成组链接法:
练习题:
4195物理块是第4196个物理块(因为是题⽬是从0开始计算的).
⽽系统中字长为32位,所以该物理块的使⽤情况应该在位⽰图的 (物理块编号+1)/系统字长 ,即是(4195+1)/32=131.25
131.25说明前131个字都有描述物理块,⽽他刚好在132个字被描述.
想要将4195号物理块分配给某⽂件,所以这个时候应该描述该任务为1,表⽰被占⽤.
想要得知在哪个位置上描述,可以先计算出上⼀个字的描述的最后⼀个物理块的位置
131*32=4192,4192-1=4191,所以131字描述的最后⼀个物理块是4191编号的物理块
所以4191号物理块的下⼀个物理块4192号物理块是在132的第0个位置被描述其使⽤情况.
以此类推4193号就是132字第⼀个位置.
即4195号物理块是132字的第三个位置被描述其使⽤情况的.
所以答案是D和B.。
在文件存储设备管理中,三类常用字的空闲块管理方法
在文件存储设备管理中,三类常用字的空闲块管理方法文件存储设备管理中的空闲块管理方法简介在文件存储设备管理中,对于空闲块的管理是非常重要的。
空闲块是指存储设备中尚未被使用的块或扇区。
本文将详细介绍三种常用的空闲块管理方法。
方法一:位图法位图法是一种常见的空闲块管理方法。
它通过一个位图来表示存储设备中的每个块的使用情况。
1.创建一个位图,每个位表示一个块。
2.当一个块被占用时,对应位图上的位被设置为1,表示被占用。
3.当一个块被释放时,对应位图上的位被设置为0,表示变为空闲。
该方法的优点是简单高效,但是位图的大小与存储设备的块数成正比,当存储设备较大时,位图的大小也会相应增大。
方法二:空闲链表法空闲链表法是另一种常用的空闲块管理方法。
它通过链表的形式来管理存储设备中的空闲块。
1.维护一个空闲块链表,链表中的每个节点表示一个空闲块。
2.当一个块被占用时,从空闲块链表中删除对应的节点。
3.当一个块被释放时,将该块加入到空闲块链表的末尾。
该方法的优点是节省空间,因为链表节点只需要额外记录下一个节点的指针即可。
但是在查找空闲块时需要遍历链表,效率较低。
方法三:索引表法索引表法是一种较为复杂的空闲块管理方法。
它通过索引表来记录存储设备中的所有块的使用情况。
1.创建一个索引表,表中的每个项表示一个块,包括块的地址和使用标记。
2.当一个块被占用时,在索引表中标记对应的项为已使用。
3.当一个块被释放时,将对应的索引表项标记为未使用。
该方法的优点是可以减少存储设备的访问时间,因为索引表可以直接定位到对应的块。
缺点是索引表需要额外的空间来存储,且操作复杂。
总结以上介绍了三种常用的空闲块管理方法:位图法、空闲链表法和索引表法。
每种方法都有其优缺点,选择合适的方法需要根据具体情况来决定。
在实际应用中,可以根据存储设备的大小、访问模式等因素进行选择和优化。
对于每种空闲块管理方法,我们来进一步了解它们的特点和适用场景。
1. 位图法•特点:简单高效,易于实现和理解。
位示图管理磁盘存储空间用位示图管理磁盘存储空间用位示图管理磁盘存储空间用位示图管理磁盘存储空间
用位示图管理磁盘存储空间一、实习内容模拟磁盘空闲空间的表示方法,以及模拟实现磁盘空间的分配和回收。
二、实习目的磁盘初始化时把磁盘存储空间分成许多块(扇区),这些空间可以被多个用户共享。
用户作业在执行期间常常要在磁盘上建立文件或把已经建立在磁盘上的文件删去,这就涉及到磁盘存储空间的分配和回收。
一个文件存放到磁盘上,可以组织成顺序文件(连续文件)、链接文件(串联文件)、索引文件等,因此,磁盘存储空间的分配有两种方式,一种是分配连续的存储空间,另一种是可以分配不连续的存储空间。
怎样有效地管理磁盘存储空间是操作系统应解决的一个重要问题,通过本实习使学生掌握磁盘存储空间的分配和回收算法。
三、实验分析连续的磁盘存储空间的分配和回收。
四、算法及说明(1) 为了提高磁盘存储空间的利用率,可在磁盘上组织成链接文件、索引文件,这类文件可以把逻辑记录存放在不连续的存储空间。
为了表示哪些磁盘空间已被占用,哪些磁盘空间是空闲的,可用位示图来指出。
位示图由若干字节构成,每一位与磁盘上的一块对应,“1”状态表示相应块已占用,“0”状态表示该块为空闲。
(2) 申请一块磁盘空间时,由分配程序查位示图,找出一个为“0”的位,计算出这一位对应块的磁盘物理地址,且把该位置成占用状态“1”。
假设现在有一个盘组共8个柱面,每个柱面有2个磁道(盘面),每个磁道分成4个物理记录。
那么,当在位示图中找到某一字节的某一位为“0”时,这个空闲块对应的磁盘物理地址为:柱面号=字节号磁道号= 位数/ 4物理记录号= 位数% 4(3) 归还一块磁盘空间时,由回收程序根据归还的磁盘物理地址计算出归还块在位示图中的对应位,把该位置成“0”。
按照(2)中假设的盘组,归还块在位示图中的位置计算如下:字节号=柱面号位数=磁道号 4+物理记录号五、用到的数据结构及模块说明int area[8][8]; 表示位示图,每一位与磁盘上的一块对应,“1”状态表示相应块已占用,“0”状态表示该块为空闲。
国家开放大学《操作系统》形考任务(简答题)参考答案
国家开放大学《操作系统》形考任务(简答题)参考答案1.简述操作系统的定义。
参考答案:操作系统是控制和管理计算机系统内各种硬件和软件资源、有效地组织多道程序运行的系统软件(或程序集合),是用户与计算机之间的接口。
2.在计算机系统中操作系统处于什么地位?参考答案:操作系统是裸机之上的第一层软件,与硬件关系尤为密切。
它不仅对硬件资源直接实施控制、管理,而且其很多功能的完成是与硬件动作配合实现的,如中断系统。
操作系统的运行需要有良好的硬件环境。
操作系统是整个计算机系统的控制管理中心,其他所有软件都建立在操作系统之上。
操作系统对它们既具有支配权力,又为其运行建造必备环境。
在裸机上安装了操作系统后,就为其他软件的运行和用户使用提供了工作环境。
3.操作系统的主要功能有哪些?参考答案:操作系统的主要功能包括:存储管理,进程和处理机管理,文件管理,设备管理以及用户接口管理。
4.操作系统一般为用户提供了哪三种界面?各有什么特点?参考答案:操作系统一般为用户提供的三种界面是:图形用户接口、命令行接口和程序接口。
图形用户接口:用户利用鼠标、窗口、菜单、图标等图形界面工具,可以直观、方便、有效地使用系统服务和各种应用程序及实用工具。
命令行接口:在提示符之后用户从键盘上输入命令,命令解释程序接收并解释这些命令,然后把它们传递给操作系统内部的程序,执行相应的功能。
程序接口:也称系统调用接口。
是操作系统内核与用户程序、应用程序之间的接口。
5.操作系统主要有哪三种基本类型?各有什么特点?参考答案:主要有以下三种基本类型:多道批处理系统、分时系统和实时系统。
多道批处理系统的特点是多道和成批。
分时系统的特点是同时性、交互性、独立性和及时性。
实时系统一般为具有特殊用途的专用系统,其特点是交互能力较弱、响应时间更严格、对可靠性要求更高。
6.使用虚拟机,有什么优势和不足?参考答案:采用虚拟机的优点主要有:在一台机器上可同时运行多个操作系统,方便用户使用。
计算机操作系统第七章--磁盘调度
7.1.1磁盘性能简述
2.移动头磁盘 每个盘面配一个磁头,装入磁臂 中,为能访问该盘面上的所有磁道,该 磁头必须移动进行寻道。移动头磁盘只 能进行串行读/写,I/O速度较慢,但结 构简单,广泛地用于中、小型磁盘设备 中。在微机上配置的温盘(温彻斯特)和 软盘,都采用移动磁头结构,故本节主 要针对这类磁盘的I/O进行讨论。
7.1.3 各种扫描算法
N步SCAN算法是将磁盘请求队 列分成若干个长度为N的子队列,磁 盘调度将按FCFS算法依次处理这些 子队列。每处理一个队列时,又是 按SCAN算法,对一个队列处理完后 又处理其它队列,这样就可避免出 现粘着现象。
7.1.3 各种扫描算法
当N值取得很大时,会使N步扫描 算法的性能,接近于SCAN算法的性 能,当N=1时,N步SCAN算法退化 为FCFS算法。
58
55 39
32
3 16
38
18
1
20
平均寻道长度:27.8
7.1.3 各种扫描算法
二、循环扫描CSCAN(Circular SCAN)单 向扫描 SCAN算法既能获得较好的性能, 又能访止进程饥饿,广泛用于大、中、 小型 机和网络中的磁盘调度。
7.1.3 各种扫描算法
问题:当磁头刚从里向外移动过 某一磁道时,恰有一进程请求访问 此磁道,这时该进程必须等待,待 磁头从里向外,然后再从外向里扫 描完所有要访问的磁道后,才处理 该进程的请求,致使该进程的请求 被严重地推迟。
7.1.3 各种扫描算法
被访问的下 一个磁道号 150 160 184 18 38 39 55 58 90 移动距离 (磁道数) 50 10 24 166 20 1 16 3 32
平均寻道长度:27.5
利用二进制位来表示磁盘中盘块空闲情况的方法(一)
利用二进制位来表示磁盘中盘块空闲情况的方法(一)利用二进制位表示磁盘中盘块空闲情况引言在计算机系统中,磁盘是一种重要的存储介质。
为了管理磁盘上不同的盘块,我们需要记录盘块的空闲情况。
一种常见的方法是利用二进制位来表示盘块的空闲情况。
本文将详细介绍几种常见的方法。
方法一:位图法位图法是一种使用位图来记录盘块的空闲情况的方法。
位图由多个字节组成,每个字节表示一个盘块的状态,其中每个比特位表示该盘块是否空闲。
比如,0表示空闲,1表示已被占用。
利用位图法来表示磁盘中盘块的空闲情况,可以使用以下步骤:1. 初始化位图,将所有的比特位置为0,表示所有盘块均为空闲。
2. 当一个盘块被占用时,将对应的比特位置为1。
3. 当需要查找空闲盘块时,遍历位图找到第一个为0的比特位所对应的盘块。
优点: - 简单、直观,易于实现和理解。
- 占用的存储空间相对较小。
缺点: - 当磁盘较大时,位图占用的存储空间会较大。
- 查找空闲盘块的效率较低,需要逐一遍历位图。
方法二:位示图法位示图法是位图法的改进版,通过使用更小的单位来记录盘块的空闲情况。
比如,一个字节可以表示8个盘块的状态,一个位可以表示一个盘块的状态。
利用位示图法来表示磁盘中盘块的空闲情况,可以使用以下步骤:1. 初始化位示图,将所有的位置为0,表示所有盘块均为空闲。
2.当一个盘块被占用时,将对应的位置为1。
3. 当需要查找空闲盘块时,首先找到一个字节中值为0的位,然后根据位的位置计算出对应的盘块。
优点: - 存储空间占用更小,比位图法更节约空间。
- 查找空闲盘块的效率较高,因为一次可以处理多个盘块。
缺点: - 实现相对复杂,需要进行位操作。
- 当磁盘较大时,位示图占用的存储空间仍然会较大。
方法三:链表法链表法是一种使用链表来记录盘块的空闲情况的方法。
每个链表节点表示一个盘块,将空闲的盘块通过链表链接起来,已被占用的盘块不在链表中。
利用链表法来表示磁盘中盘块的空闲情况,可以使用以下步骤:1. 初始化链表,将所有盘块都加入链表中。
自考操作系统问答题
1. 操作系统结构设计应追求的目标是什么?正确性、高效性、维护性、移植性。
2. 在磁盘存储空间管理的位示图法中,确定已知空闲块地址的块号、柱面号的通用公式为:块号=字号×字长+位号柱面号=\[块号/柱面上的块数\]请写出确定空闲块地址的磁头号和扇区号的通用公式。
答案:磁头号=\[(块号mod柱面上的块数)/盘面上的扇区数\]扇区号=(块号mod柱面上的块数)mod盘面上的扇区数3. UNIX系统调用close是如何处理的?清除有关的表项。
检查块设备的缓冲区是否还有信息未写回,若有,则写回设备。
检查是否有其他进程仍打开此设备,若有,则不能关闭此设备。
若无其他进程打开此设备,调用驱动程序中的关闭过程,与设备断开。
4. 什么是线程?简述进程与线程的关系。
线程是进程中可独立执行的子任务。
一个进程中可以有一个或多个线程。
一个进程中的各个线程可以并发执行。
系统为进程分配主存空间,同一进程中的各线程共享该进程的主存空间。
5. 操作系统采用层次结构设计方法有什么优点和难点?主要优点是有利于系统的设计与调试,主要困难在于层次的划分和安排。
6. 目录结构有一级、二级和树形目录结构。
请简单叙述树形目录结构的优点。
解决了重名问题;有利于文件分类;提高检索文件的速度;能进行存取权限的控制。
7. 简述UNIX中系统调用命令OPEN的处理过程。
(1)分配一个活动索引节点,引用计数i_count加1。
(2)在进程打开文件表和系统打开文件表中分配表项。
(3)调用设备驱动程序检查打开的合法性。
(4)初始化驱动程度的数据结构。
(5)建立进程和设备间的联系。
8. 比较进程同步和进程互斥的异同。
答案:同:两者都是对并发进程竞争共享资源的管理。
异:进程互斥——各进程竞争共享资源没有必然的逻辑顺序。
只要无进程在使用共享资源就允许任一进程去使用。
进程同步——对共享资源的使用有一定的逻辑顺序。
9. 某系统有同类资源m个,供n个进程共享,如果每个进程最多申请x(1≤x≤m)个资源,且各进程的最大需求量之和小于(m+n)个资源,证明该系统不会发生死锁。
用位示图管理磁盘空间的分配与回收.doc
袇课程设计报告螈(2016--2017年度第二学期):操作系统实验薆课程名称:用位示图管理磁盘空间的分配与回收袃课设题目:控制与计算机工程学院羇院系:信安1401羅班级:黄竞昶羃姓名:贾静平薂指导教师:一周肇设计周数:莆成绩年 7月 9日螅2015莀一、需求分析蒁要求打印或显示程序运行前和运行后的位示图,以及分配和回收磁盘的物理地址过程。
螆( 1)假定现有一个磁盘组,共 40 个柱面。
每个柱面 4 个磁道,每个磁道又划分成 4 个物理记录。
磁盘的空间使用情况用位示图表示。
位示图用若干个字构成,每一位对应一个磁盘块。
1 表示占用, 0 表示空闲。
为了简单,假定字长为 16 位,其位示图如图 9— 1 所示。
系统设一个变量 S,记录磁盘的空闲块个数。
莃蒁 1 膇 2 袅 3 膂 4 薁 5 薈 6 莃 7 羁 8 蚀 9 蚅肅蚀螀肆薃膃位10 11 12 13 14 15袀螃字 0 蒇 1 芅 1 薂 1 羀 1 袈 1 蚂 0 芁 1 肀 0 羄 0 莄 1 聿 1 肀 1 莅 1 袂 1 肂 01膀 1袆 2....袁 39芀图 9—1 位示图( 2)申请一个磁盘块时,由磁盘块分配程序查位示图,找出一个为0 的位,并计算磁盘的芇物理地址 ( 即求出柱面号、磁道号 ( 也即磁头号 ) 和扇区号 ) 。
肂由位示图计算磁盘的相对块号的公式如下:蚀相对块号一字号× 16+位号荿之后再将相对块号转换成磁盘的物理地址:蚈由于一个柱面包含的扇区数=每柱面的磁道数×每磁道的扇区数=4× 4= 16,故柱面号=相对块号/ 16 的商,即柱面号=字号螄磁道号= ( 相对块号/ 16 的余数 ) /4 的商,即 ( 位号/ 4) 的商蚃物理块号= ( 相对块号/ 16 的余数 ) / 4 的余数,即 ( 位号/ 4) 的余数葿( 3)当释放一个相对物理块时,运行回收程序,计算该块在位示图中的位置,再把相应位置 0。
位示图方法模拟磁盘块的分配与回收
位示图方法模拟磁盘块的分配与回收题目的描述:1.要求在LINUX环境用C语言编程2.假设有一个500行500列的矩阵来表示磁盘块,状态位是1表示已经分配出去,状态位是0表示空闲块3.给这个矩阵用随机函数初始化,让其布满0和14.写程序统计有多少个空闲块?5.有一个程序文件要申请20个磁盘块,能否分配?如果可以分配,给出分配块的块号地址,块号=字号×500+位号,并修改位示图,块号从0开始编址。
6.要回收第300块和第580块,如何实现?给出位示图修改的程序在linux系统中,我想很多的朋友使用的是虚拟机,这样的话,当我们将行和列都设置为500x500的话,操作就不是很方便了,所以呢,小Q就将其修改为10X10的来演示就好了,其中的算法和思想是完全相同的。
另外一点,必须声明,在linux中使用vi编辑器进行C语言的编程,其中是不允许含有中文的,即使是中文的注释也不行。
为了,朋友们好理解,我再这里写注释的时候使用的是中文的注释,但是你在使用的时候一定要记住不能将其放入到linux环境下的vi编辑器中。
好了,我想建立文件什么的我就不用讲了,下面看下,如何解决上述的问题吧,就算是抛砖引玉吧。
/*使用变量:row表示行,col表示列*/#include <stdio.h>#include <sys/time.h>#include <fcntl.h>#define row 10#define col 10void init_random (){unsigned int ticks;struct timeval tv;int fd;gettimeofday (&tv, NULL);ticks = _sec + _usec;fd = open ("/dev/urandom", O_RDONLY);if (fd > 0){unsigned int r;int i;for (i = 0; i < 512; i++){read (fd, &r, sizeof (r));ticks += r;}close (fd);}srand (ticks);//printf("init finished ");}unsigned int new_rand (){int fd;unsigned int n = 0;fd = open ("/dev/urandom", O_RDONLY);if (fd > 0){read (fd, &n, sizeof (n));}close (fd);return n;}int statistics_free(unsigned int wst[][]){int sum_free=0;//记录空闲块个数,并初始化int i_row=0;int i_col=0;for(;i_row<row;i_row++)for(i_col=0;i_col<col;i_col++){if(wst[i_row][i_col]==0)sum_free++;}return sum_free;}void ask_space(unsigned int wst[][],int ask) {int i_row=0;int i_col=0;int t_row=0;int t_col=0;if(ask>statistics_free(wst)){printf("The space don't enough");return;}printf("The space address like this:\n");for(;i_row<row;i_row++)for(i_col=0;i_col<col;i_col++){int address=0;if(ask>0&&wst[i_row][i_col]==0){wst[i_row][i_col]=1;ask--;//计算当前的分配块号的地址address=i_row*row+i_col;printf("%d ",address);}else if(ask==0){printf("\nThe ask had request,the array is changed:\n");for(t_row=0;t_row<row;t_row++){for(t_col=0;t_col<col;t_col++)printf("%d ",wst[t_row][t_col]);printf("\n");}return;}}}void recover_space(unsigned int wst[row][col],int recover_number){int r_row=0;int r_col=0;r_row=recover_number/col;r_col=recover_number%col;if(r_row>row-1){printf("Your ask to free space don't find.");return;}wst[t_row][t_col]=0;printf("\nThe ask had request,the array is changed:\n");for(r_row=0;r_row<row;r_row++){for(r_col=0;r_col<col;r_col++)printf("%d ",wst[r_row][r_col]);printf("\n");}printf("\n");}int main (){//int n, i;//init_random ();//调用内部的接口进行设置随机种子。
操作系统阶段测评三
操作系统-阶段测评31. 单选题1.1 3.0下面对移臂调度算法的描述错误的是(d)您答对了«a移臂调度的目的是减少寻找时间,包括先来先服务、最短寻找时间优先、电梯调度、单向扫描等算法* b先来先服务调度算法不考虑访问要求的物理位置,只考虑提出请求的先后次序* c最短寻找时间优先、电梯调度和单向扫描算法根据访问请求的柱面位置调度«d相比之下先来先服务调度算法是最简单实用且花费时间短的算法1.2 3.0下列关于SPOOLIN(系统的说法不正确的是(d)您答错了* aSPOOLING是Simultaneous Peripheral Operation On Line 的缩写,又称斯普林系统* bSPOOLIN係统由预输入程序、井管理程序和缓输出程序三部分组成* c操作系统实现虚拟设备的功能模块是在计算机控制下通过联机的外围设备同时操作来实现其功能的* dSPOOLIN(系统是一种类似于通道的硬件设备,是实现独占设备与共享设备的映射1.3 3.0磁盘上的某个磁道被划分成四块,磁盘的转速为20毫秒/转,当前磁头在第二块的开始位置,则花费(b)毫秒的时间可把第一块信息读到主存。
(假设旋转是按由块号从小到大方向的)您答对了«a40«b20* c10* d51.4 3.0对磁盘而言,输入输出操作的信息传送单位为:(b)您答对了* a字符* b块文件考察I/O的信息传递单位。
1.5 3.0在通道结构中,操作系统启动和控制外围设备完成输入/输出操作的过程(a)您答对了* a包括准备、启动I/O和结束处理三个阶段* b包括启动、选择通道和设备、控制设备处理输入/输出操作和完成处理几个步骤* c包含启动I/O等特权准备,是一种访管中断,属于强迫性中断事件* d不属于“设备处理一致性”的处理方法本题考查的知识点为输入/输出操作控制。
操作系统启动和控制外围设备完成输入/输出操作的过程可分为以下三个阶段:(1)准备阶段。
简述外存空闲空间管理的方法
外存空闲空间管理是指在计算机系统中,有效地管理外部存储设备(如硬盘驱动器)中的空闲空间,以便于文件的存储和检索。
以下是几种常见的外存空闲空间管理方法:
位图法(Bit-Map):位图法使用一个位图来表示外存空间中的每个块的使用情况,其中每个位对应一个块。
位图中的0表示空闲块,1表示已分配块。
通过对位图进行操作,可以快速地找到空闲块并进行分配。
空闲链表法(Free List):空闲链表法使用一个链表来存储空闲块的地址信息。
链表中的每个节点记录一个空闲块的起始地址和长度。
当需要分配空闲块时,从链表中选择合适大小的节点,并将其从链表中移除。
当空闲块被释放时,将其插入链表合适的位置。
空闲区域表法(Free Space Table):空闲区域表法将外存空间划分为多个区域,并使用一个表来记录每个区域的起始地址和长度。
当需要分配空闲块时,遍历空闲区域表,找到满足大小需求的空闲区域并进行分配。
当空闲块被释放时,将其合并到相邻的空闲区域,更新空闲区域表。
分区管理(Partitioning):分区管理将外存空间划分为固定大小的分区,每个分区独立管理。
每个分区可以采用不同的管理方法,如位图法、空闲链表法等。
通过分区管理,可以提高外存空间的利用率和文件存取的效率。
在实际应用中,不同的文件系统和操作系统可能采用不同的外存空闲空间管理方法,以适应不同的需求和性能要求。
综合考虑空间利用率、分配速度、碎片化等因素,选择合适的外存空闲空间管理方法对于有效管理外部存储设备是至关重要的。
模拟实现用位示图法管理文件存储空间的分配与回收
合肥学院计算机科学与技术系课程设计报告20011~2012 学年第1 学期课程名称操作系统原理课程设计名称模拟实现用位示图法管理文件存储空间的分配与回收专业班级学生姓名学生学号指导教师20011 年11 月实验题目模拟用位示图法管理文件存储空间的分配与回收一、实验目的:1)理解文件存储空间的分配与回收的基本概念,掌握产生文件存储空间的分配与回收的几种方法,体会位示图算法是管理文件存储空间的分配与回收的一种行之有效的方法。
2)通过编写程序实现位示图算法,进一步理解位示图算法的原理和执行过程,掌握位示图算法的描述和应用,进一步熟练掌握文件存储空间的分配与回收的方法。
二、实验内容:(1)首先对位示图算法原理进行深刻的理解和掌握;(2)程序首先要给出位示图初态。
分配时,参数为文件名及需要分配的块数。
回收时,参数为文件名。
(3)回答信息:分配时,能够分配时,给出文件名和分配的具体块号。
否则,给出无法分配的信息。
显示位示图。
(4)回收时:给出回收的具体块号。
显示位示图。
三、实验环境Windows系统,在C++的环境下来运行这儿程序四、实验主要步骤1、初始化及使用数据结构对数组WST[]元素初始化为0。
定义以下3个链表并初始化。
空闲区结构体定义free_link、申请空间作业结构体定义office、相关位示图操作的结构体定义work。
位示图算法是利用二进制的一位来表示磁盘中的一个盘块的使用情况。
在外存上建立一张位示图(bitmap),记录文件存储器的使用情况。
每一位仅对应文件存储器上的一个物理块,取值0和1分别表示空闲和占用。
文件存储器上的物理块依次编号为:0、1、2、…。
定义为一维数组WST[],操作起来更为方便。
下表号与盘块号对应。
在输出的时候控制输出为二维形式。
112、申请空间算法首先要输入文件名和大小,查找与已存在的文件是否重名。
没有,则比较空闲区中空闲块数是否大于欲分配的块数。
有的话分配。
分配的时候该作业要记录下自己所占盘块的其实盘号和所占用的盘快数。
《操作系统原理》习题库及参考答案05文件管理
第5章文件管理习题一、填空1.一个文件的文件名是在时给出的。
2.所谓“文件系统”,由与文件管理有关的、被管理的文件以及管理所需要的数据结构三部分组成。
3.是辅助存储器与内存之间进行信息传输的单位。
4.在用位示图管理磁盘存储空间时,位示图的尺寸由磁盘的决定。
5.采用空闲区表法管理磁盘存储空间,类似于存储管理中采用方法管理内存储器。
6.操作系统是通过感知一个文件的存在的。
7.按用户对文件的存取权限将用户分成若干组,规定每一组用户对文件的访问权限。
这样,所有用户组存取权限的集合称为该文件的。
8.根据在辅存上的不同存储方式,文件可以有顺序、和索引三种不同的物理结构。
9.如果把文件视为有序的字符集合,在其内部不再对信息进行组织划分,那么这种文件的逻辑结构被称为“”。
10.如果用户把文件信息划分成一个个记录,存取时以记录为单位进行,那么这种文件的逻辑结构称为“”。
11. 操作系统应该提供一个环境,保证信息使用的私密和共享,这是系统的安全问题;另一方面,操作系统还需要提供各种手段,防止来自各方的有意或无意的入侵和攻击,这是系统的安全问题。
12. “文件备份”的含义,就是为系统中的文件建立相应的副本。
它通常有两种方法,一是所谓的“转储”,一是所谓的“转储”。
13. 用户总是从使用的角度出发去组织文件,系统则总是从的角度出发去组织文件的。
14. 在记录式文件中,总要有一个数据项能够唯一地标识记录,以便对记录加以区分。
文件中的这种数据项被称为或。
二、选择1.下面的不是文件的存储结构。
A.索引文件B.记录式文件C.串联文件D.连续文件2.有一磁盘,共有10个柱面,每个柱面20个磁道,每个盘面分成16个扇区。
采用位示图对其存储空间进行管理。
如果字长是16个二进制位,那么位示图共需字。
A.200 B.128 C.256 D.1003.操作系统为每一个文件开辟一个存储区,在它的里面记录着该文件的有关信息。
这就是所谓的。
A.进程控制块B.文件控制块C.设备控制块D.作业控制块4.文件控制块的英文缩写符号是。
操作系统:位示图法模拟磁盘管理的程序,请帮忙改一下错误..doc
操作系统:位示图法模拟磁盘管理的程序,请帮忙改一下错误.#include<stdio.h>#include<malloc.h>#include<stdafx.h>void display(int disk[8][8])//显示位示图{int i,j;printf(" 磁道0记录块磁道1记录块\n");printf("记录块序号\t0 1 2 3 \t 4 5 6 7\n" );for(i=0;i<8;i++){printf("\n柱面%d:",i);for(j=0;j<8;j++)printf("%d",disk[i][j]);}}int maxspace(int disk[8][8])//返回最大的连续空间{int i=0;int j=0;int num=0;int max=0;for(i=0;i<8;i++){for(j=0;j<8;j++)if(disk[i][j]==0)num++;else if(num>max){max=num;num=0;}else num=0;}return max;}void feipei(int disk[8][8])//分配程序{int i=0;int j=0;int num=0;int space;int max;int ii;int jj;int m;int n ;int g;int gg;int k;int kk;int z;int c;int x;printf("请输入请求分配的空间大小:");B:scanf("%d",&space);while(space<=0){printf("\n输入非法,你输入的空间大小是负数!请重输:");scanf("%d",&space);}//goto B;max= maxspace(disk[8][8]);if(max==0)printf("\n已经没有空闲区可以分配了!");else{ if(space>max){printf("\n要求空间太大,没有满足要求的空间。
模拟实现用位示图法管理文件存储空间的分配与回收1
计算机科学与技术学院《操作系统》综合试验报告(2016/2017学年第一学期)学生姓名:学生专业:网络工程学生班级:网络班学生学号: 2指导教师:2016年12月12日计算机科学与技术学院综合试验任务书目录第一章功能需求描述 (1)1.1功能列表与说明 (1)1.2 操作界面 (1)1。
3 界面操作 (1)第二章系统设计描述 (2)2。
1 任务分解说明 (2)2.2主要数据结构设计说明 (2)2。
3主要函数接口说明 (3)第三章算法设计描述 (5)3.1主要函数和函数的流程图 (5)3。
1。
1。
盘块的分配算法流程图 (5)3.2.2.盘块的回收算法流程图 (6)第四章开发过程描述 (7)4。
1 程序源码 (7)4。
2 程序中遇到的错误及错误原因 (7)4。
3测试程序功能所用的数据和测试方法 (7)第五章设计心得体会 (8)附录1 程序源代码 (9)第一章功能需求描述1.1功能列表与说明1.2 操作界面文件的存取和回收1。
分配文件2。
回收文件3。
退出请输入选项:1.3 界面操作如图可以很清楚的看到可以输入1 2 3 三个数分别对应分配文件、回收文件、退出三种操作。
第二章系统设计描述2.1 任务分解说明1. 位示图法系统初始化。
2 。
位示图法分配与回收算法。
2。
2主要数据结构设计说明1。
空闲区结构体定义typedef struct node{int start_location; //空闲区对象变量的开始位置int free_number; //空闲区块数目struct node*next; //指向下一个空闲区的指针}free_link;2。
申请空间作业结构体定义typedef struct link{char office[20];//作业名int begin_location; //作业申请空间后的开始位置int office_number; //作业申请空间区的数目struct link *next; //指向下一个申请空闲区的作业指针}office;3。
操作系统 文件存储空间管理 位示图法
#include <stdio.h>#include <memory.h>#include <string>#include <iostream>using namespace std;struct FCB{char fname[16]; //文件名int type; //1代表普通文件2代表目录文件0表示空文件int size; //文件大小int fatherBlockNum; //当前的父目录盘块号int firstBlockNum; //该文件第一个盘块号int currentBlockNum; //当前的盘块int lastBlockNum;void initialize(){strcpy(fname,"\0");type = 0;size =0;fatherBlockNum = firstBlockNum = currentBlockNum =lastBlockNum= 0; }};/*常量设置*/const char* FilePath = "C:\\myfiles";const int BlockSize = 512; //盘块大小(可配置)const int OPEN_MAX = 5; //能打开最多的文件数const int BlockCount = BlockSize/sizeof(int); //盘块数const int DiskSize = BlockSize*BlockCount; //磁盘大小const int BlockFcbCount = BlockSize/sizeof(FCB);//目录文件的最多FCB数const int m=16; //位示图的列数const int n=BlockCount/m; //位示图的行数//const int IOBUF_SIZE = 512;//char IOBuffer[IOBUF_SIZE];int OpenFileCount = 0;struct OPENLIST //用户文件打开表{int files; //当前打开文件数FCB f[OPEN_MAX]; //FCB拷贝OPENLIST(){files=0;for(int i=0;i<OPEN_MAX;i++){f[i].fatherBlockNum=-1;//为分配打开f[i].type=0;}}};/*-------------目录文件结构---------------*/struct dirFile{struct FCB fcb[BlockFcbCount];void init(int _FatherBlockNum,int _FirstBlockNum, int _CurrentBlockNum,int _LastBlockNum,char *name)//父块号,第一个盘块号,当前块号,目录名{strcpy(fcb[0].fname,name); //本身的FCBfcb[0].fatherBlockNum=_FatherBlockNum;fcb[0].firstBlockNum=_FirstBlockNum;fcb[0].currentBlockNum=_CurrentBlockNum;fcb[0].lastBlockNum=_LastBlockNum;fcb[0].type=2; //标记目录文件for(int i=1;i<BlockFcbCount;i++){fcb[i].fatherBlockNum=_CurrentBlockNum; //标记为子项fcb[i].type=0; // 标记为空白项}}};/**********************************************************************/struct DISK{int FAT1[BlockCount]; //FAT1int FAT2[BlockCount]; //FAT2struct dirFile root; //根目录int map[n][m]; //位示图,最初都为0int check[n][m]; //check数组用于一致性检查,作为数据计数器;char data[BlockCount-5][BlockSize];void format(){memset(FAT1,0,BlockCount); //FAT1memset(FAT2,0,BlockCount); //FAT2FAT1[0]=FAT1[1]=FAT1[2]=FAT1[3]=FAT1[4]=-2; //0,1,2盘块号依次代表FAT1,FAT2,根目录区FAT2[0]=FAT2[1]=FAT2[2]=FAT2[3]=FAT2[4]=-2; //FAT作备份root.init(2,2,2,2,"G:\\");//根目录区for(int i=0;i<=BlockCount;i++) //map[0][0],map[0][1],map[0][1],map[0][2],map[0][3],map[0][4]以及check{ //对应位置为占用if(i<5){map[0][i]=0;check[0][i]=1;}else{map[i/16][i%16]=1;check[i/16][i%16]=0;}}memset(data,0,sizeof(data));//数据区}};/*-----------------全局变量--------------------------*/FILE *fp; //磁盘文件地址char * BaseAddr; //虚拟磁盘空间基地址string currentPath="G:\\"; //当前路径int current=2; //当前目录的盘块号string cmd; //输入指令struct DISK *osPoint; //磁盘操作系统指针char command[16]; //文件名标识struct OPENLIST* openlist; //用户文件列表指针/*-----------函数事先申明--------------------*/int format();int mkdir(char *sonfname);int rmdir(char *sonfname);int create(char *name);int listshow();int delfile(char *name);int changePath(char *sonfname);int write(char *name);int exit();int open(char *file);int close(char *file);int read(char *file);/*------------初始化-----------------------*/int format(){current = 2;currentPath="G:\\"; //当前路径osPoint->format();//打开文件列表初始化delete openlist;openlist=new OPENLIST;/*-------保存到磁盘上myfiles--------*/fp = fopen(FilePath,"w+");fwrite(BaseAddr,sizeof(char),DiskSize,fp);fclose(fp);printf("----------------------------------------------------------\n\n"); return 1;}/*-----------------------创建子目录-------------------*/int mkdir(char *sonfname){//判断是否有重名//寻找空白子目录项//寻找空白盘块号//当前目录下增加该子目录项//分配子目录盘块,并且初始化//修改fat表int i,temp,iFAT;struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-5]);/*--------为了避免该目录下同名文件夹--------*/for(i = 1;i<BlockFcbCount;i++){if(dir->fcb[i].type==2 && strcmp(dir->fcb[i].fname,sonfname)==0 ) {printf("该文件夹下已经有同名的文件夹存在了!\n");return 0;}}//查找空白fcb序号for(i=1;i<BlockFcbCount;i++){if(dir->fcb[i].type==0)break;}if(i==BlockFcbCount){printf("该目录已满!请选择新的目录下创建!\n");return 0;}temp=i;for(i = 5;i < BlockCount;i++){if(osPoint->map[i/m][i%m] > 0)break;}if(i == BlockCount){printf("磁盘已满!\n");return 0;}iFAT=i;/*-------------接下来进行分配----------*/osPoint->map[iFAT/m][iFAT%m]--; //对应盘块在位示图置0;osPoint->FAT1[iFAT]=osPoint->FAT2[iFAT]= iFAT; //每个目录文件只占一块所以在文件分配表中其链接的下一块为其本身osPoint->check[iFAT/m][iFAT%m]++; //对应盘块在数据计数器中置1;//填写该分派新的盘块的参数strcpy(dir->fcb[temp].fname,sonfname);dir->fcb[temp].type=2;dir->fcb[temp].fatherBlockNum=current;dir->fcb[temp].firstBlockNum=iFAT;dir->fcb[temp].currentBlockNum=iFAT;dir->fcb[temp].lastBlockNum=iFAT;//初始化子目录文件盘块dir=(struct dirFile*)(osPoint->data [iFAT-5]); //定位到子目录盘块号dir->init (current,iFAT,iFAT,iFAT,sonfname);//iFAT是要分配的块号,这里的current用来指要分配的块的父块号printf("---------------------------------------------------------------\n\n");return 1;}/*-------删除当前目录下的文件夹--------*/int rmdir(char *sonfname){//if(子目录不存在) return error//if(子目录不是空文件夹) return error//回收子目录磁盘块号b(修改fat)//回收子目录占据目录项int i,temp,j;//确保当前目录下有该文件,并记录下该FCB下标struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-5]);for(i=1;i<BlockFcbCount;i++){ //查找该目录文件if(dir->fcb[i].type==2 && strcmp(dir->fcb[i].fname,sonfname)==0){break;}}temp=i;if(i==BlockFcbCount){printf("当前目录下不存在该子目录!\n");return 0;}j = dir->fcb[temp].currentBlockNum;struct dirFile *sonDir; //当前子目录的指针sonDir=(struct dirFile *)(osPoint->data [ j - 5]);for(i=1;i<BlockFcbCount;i++) //查找子目录是否为空目录{if(sonDir->fcb[i].type!=0){printf("该文件夹为非空文件夹,为确保安全,请清空后再删除!\n");return 0;}}/*开始删除子目录操作*/osPoint->FAT1[j] = osPoint->FAT2[j]=0; //fat清空osPoint->map[j/m][j%m]++; //位示图对应盘块置为空闲osPoint->check[j/m][j%m]--; //数据计数器对应盘块置为空闲char *p=osPoint->data[j-5]; //格式化子目录memset(p,0,BlockSize);dir->fcb[temp].initialize(); //回收子目录占据目录项printf("---------------------------------------------------------------\n\n"); return 1;}/*-----------在当前目录下创建文本文件---------------*/int create(char *name){int i,iFAT;//temp,int emptyNum = 0,isFound = 0; //空闲目录项个数struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-3]);//查看目录是否已满//为了避免同名的文本文件for(i=1;i<BlockFcbCount;i++){if(dir->fcb[i].type == 0 && isFound == 0){emptyNum = i;isFound = 1;}else if(dir->fcb[i].type==1 && strcmp(dir->fcb[i].fname,name)==0 ) {printf("无法在同一目录下创建同名文件!\n");return 0;}}if(emptyNum == 0){printf("已经达到目录项容纳上限,无法创建新文件!\n");return 0;}//查找位示图寻找空白区,用来分配磁盘块号jfor(i = 5;i<BlockCount;i++){if(osPoint->map[i/m][i%m] > 0)break;}if(i==BlockCount){printf("磁盘已满!\n");return 0;}iFAT=i;/*------进入分配阶段---------*///位示图分配osPoint->map[iFAT/m][iFAT%m]--;//分配磁盘块osPoint->FAT1[iFAT] = osPoint->FAT2[iFAT] = iFAT; //文件刚刚创建时只分配一块FAT连接自身//数据计数器对应位置为占用osPoint->check[iFAT/m][iFAT%m]++;/*-----------接下来进行分配----------*///填写该分派新的盘块的参数strcpy(dir->fcb[emptyNum].fname,name);dir->fcb[emptyNum].type=1;dir->fcb[emptyNum].fatherBlockNum=current;dir->fcb[emptyNum].firstBlockNum=iFAT;dir->fcb[emptyNum].currentBlockNum=iFAT;dir->fcb[emptyNum].lastBlockNum=iFAT;dir->fcb[emptyNum].size =0;char* p = osPoint->data[iFAT -5];memset(p,'#',BlockSize);printf("----------------------------------------------------------------\n\n");return 1;}/*-------查询子目录------------*/int listshow(){int i,DirCount=0,FileCount=0;//搜索当前目录struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-5]);for(i=1;i<BlockFcbCount;i++){if(dir->fcb[i].type==1){ //查找普通文件FileCount++;printf("%s 文本文件.\n",dir->fcb[i].fname);}if(dir->fcb[i].type==2){ //查找目录文件DirCount++;printf("%s 文件夹.\n",dir->fcb[i].fname);}}printf("\n该目录下共有%d 个文本文件, %d 个文件夹\n\n",FileCount,DirCount); printf("--------------------------------------------------------\n\n");return 1;}/*---------在当前目录下删除文件-----------*/int delfile(char *name){int i,temp,j;//确保当前目录下有该文件,并且记录下它的FCB下标struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-3]);for(i=1;i<BlockFcbCount;i++) //查找该文件{if(dir->fcb[i].type==1 && strcmp(dir->fcb[i].fname,name)==0){break;}}if(i==BlockFcbCount){printf("当前目录下不存在该文件!\n");return 0;}//从打开列表中删除close(name);printf("文件已删除!\n");temp=i;/*开始删除文件操作*/dir->fcb [temp].currentBlockNum=dir->fcb [temp].firstBlockNum;int next=dir->fcb [temp].currentBlockNum ;//查找盘块号jdo{j = dir->fcb [temp].currentBlockNum = next;next=osPoint->FAT1[j];osPoint->FAT1[j]=osPoint->FAT2[j]=0; //fat1,fat2表标记为空白osPoint->map[j/m][j%m]++; //位示图该盘块号对应位置为空闲osPoint->check[j/m][j%m]--; //数据计数器对应盘块号置为空闲char *p=osPoint->data[j - 5];memset(p,0,BlockSize); //清除原文本文件的内容}while(dir->fcb [temp].currentBlockNum!=dir->fcb [temp].lastBlockNum);dir->fcb[temp].initialize(); //type=0; //标记该目录项为空文件printf("------------------------------------------------------------\n\n");return 1;}/*--------------进入当前目录下的子目录--------------*/int changePath(char *sonfname){struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-5]);/*回到父目录*/if(strcmp(sonfname,"..")==0){if(current==2){printf("你现已经在根目录下!\n");return 0;}current = dir->fcb[0].fatherBlockNum ;currentPath = currentPath.substr(0,currentPath.size() - strlen(dir->fcb[0].fname )-1); return 1;}/*进入子目录*/int i,temp;//确保当前目录下有该目录,并且记录下它的FCB下标for(i = 1; i < BlockFcbCount; i++){ //查找该文件if(dir->fcb[i].type==2 && strcmp(dir->fcb[i].fname,sonfname)==0 ) {temp=i;break;}}if(i==BlockFcbCount){printf("不存在该目录!\n");return 0;}//修改当前文件信息current=dir->fcb [temp].currentBlockNum ;currentPath = currentPath+dir->fcb [temp].fname +"\\";printf("-------------------------------------------------------------\n\n"); return 1;}/*--------System exit---------------------*/int exit(){//将所有文件都关闭//保存到磁盘上C:\myfilesfp=fopen(FilePath,"w+");fwrite(BaseAddr,sizeof(char),DiskSize,fp);fclose(fp);//释放内存上的虚拟磁盘free(osPoint);//释放用户打开文件表delete openlist;printf("---------------------------------------------------------\n\n");return 1;}/*-------------在指定的文件里记录信息---------------*/int write(char *name){int i;int iFAT;int FcbIndex;char *startPoint,*endPoint;struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-5]);//在打开文件列表中查找file(还需要考虑同名不同目录文件的情况!!!)for(i=0;i<OPEN_MAX;i++){if(strcmp(openlist->f [i].fname,name)==0 ){if(openlist->f[i].fatherBlockNum ==current){break;}else{printf("该文件处于打开列表中,本系统只能改写当前目录下文件!\n");return 0;}}}if(i==OPEN_MAX){printf("该文件尚未打开,请先打开后写入信息!!\n");return 0;}int active=i;for(i = 1;i< BlockFcbCount;i++){ //查找该文件if(dir->fcb[i].type==1 && strcmp(dir->fcb[i].fname,name)==0 ){FcbIndex=i;break;}}openlist->f[active].currentBlockNum=openlist->f[active].firstBlockNum; int next=openlist->f[active].currentBlockNum;int now;while(next!=openlist->f[active].lastBlockNum){now=openlist->f[active].currentBlockNum;next=osPoint->FAT1[now];osPoint->map[next/m][next%m]++;osPoint->check[next/m][next%m]--;}int fileStartNum = openlist->f[active].currentBlockNum - 5 ; startPoint = osPoint->data[fileStartNum];endPoint = osPoint->data[fileStartNum + 1];printf("请输入文本以#号结束:\t");char input;while((input=getchar())!='#'){if(startPoint < endPoint){*startPoint++ = input;}else{for(i = 5;i<BlockCount;i++){if(osPoint->map[i/m][i%m] > 0)break;}if(i==BlockCount){printf("磁盘已满!\n");*--startPoint='#';return 0;iFAT=i;now=openlist->f[active].currentBlockNum;osPoint->map[iFAT/m][iFAT%m]--;osPoint->check[iFAT/m][iFAT%m]++;osPoint->FAT1[now]= osPoint->FAT2[now]=iFAT;openlist->f[active].currentBlockNum=iFAT;char* p = osPoint->data[iFAT -5];memset(p,'#',BlockSize);int fileStartNum = openlist->f[active].currentBlockNum - 5 ;startPoint = osPoint->data[fileStartNum];endPoint = osPoint->data[fileStartNum + 1];*startPoint++ = input;}}openlist->f[active].lastBlockNum=openlist->f[active].currentBlockNum;dir->fcb[FcbIndex].lastBlockNum=openlist->f[active].currentBlockNum; return 1;}/*---------选择一个打开的文件读取信息----------*/int read(char *file){int i,fileStartNum;char *startPoint,*endPoint;//struct dirFile *dir;//在打开文件列表中查找file(还需要考虑同名不同目录文件的情况!!!)for(i=0;i<OPEN_MAX;i++){if(strcmp(openlist->f [i].fname,file)==0 ){if(openlist->f[i].fatherBlockNum ==current){break;}else{printf("该文件处于打开列表中,本系统只能阅读当前目录下文件!\n");return 0;}}if(i==OPEN_MAX){printf("该文件尚未打开,请先打开后读取信息!\n");return 0;}int active=i;int now;//计算文件物理地址openlist->f[active].currentBlockNum=openlist->f[active].firstBlockNum; fileStartNum = openlist->f[active].currentBlockNum - 5 ;startPoint = osPoint->data[fileStartNum];endPoint = osPoint->data[fileStartNum + 1];//end_dir=(struct dirFile *)[BlockSize-1];//q=(char *)end_dir;printf("该文件的内容为: ");while((*startPoint)!='#'){if(startPoint<endPoint-1)putchar(*startPoint++);else{putchar(*startPoint);now=openlist->f[active].currentBlockNum;openlist->f[active].currentBlockNum=osPoint->FAT1[now];fileStartNum = openlist->f[active].currentBlockNum - 5 ;startPoint = osPoint->data[fileStartNum];endPoint = osPoint->data[fileStartNum + 1];}}printf("\n");return 1;}/*---------------当前目录下添加一个打开文件-------------------------*/int open(char *file)//打开文件{int i,FcbIndex;//确保没有打开过该文件= 相同名字+ 相同目录for(i=0;i<OPEN_MAX;i++){if(openlist->f[i].type ==1 && strcmp(openlist->f [i].fname,file)==0 &&openlist->f[i].fatherBlockNum == current){printf("该文件已经被打开!\n");return 0;}}//确保有空的打开文件项if(openlist->files == OPEN_MAX){printf("打开文件数目达到上限!无法再打开新文件.\n");return 0;}//确保当前目录下有该文件,并且记录下它的FCB下标struct dirFile *dir; //当前目录的指针if(current==2)dir=&(osPoint->root);elsedir=(struct dirFile *)(osPoint->data [current-3]);for(i = 1;i< BlockFcbCount;i++){ //查找该文件if(dir->fcb[i].type==1 && strcmp(dir->fcb[i].fname,file)==0 ){FcbIndex=i;break;}}if(i==BlockFcbCount){printf("当前目录下不存在该文件!\n");return 0;}//装载新文件进入打开文件列表,(FCB信息,文件数++)openlist->f[OpenFileCount] = dir->fcb[FcbIndex]; //FCB拷贝openlist->files ++;printf("文件打开成功!\n");OpenFileCount++;return 1;}int close(char *file){//释放该文件所占内存//释放用户打开文件列表表项int i;//在打开文件列表中查找file(还需要考虑同名不同目录文件的情况!!!) for(i=0;i<OPEN_MAX;i++){if((openlist->f [i].type = 1)&&(strcmp(openlist->f [i].fname,file)==0)){if(openlist->f[i].fatherBlockNum == current){break;}else{printf("该文件已打开,但未在当前目录下,无法关闭!\n");return 0;}}}if(i==OPEN_MAX){printf("该文件未在打开列表中!\n");return 0;}int active=i;openlist->files --;openlist->f[active].initialize();OpenFileCount--;printf("该文件已关闭!\n");return 1;}/*--------------位示图显示----------------------------*/int display(void){int i,j;printf("\n");printf("\t");for(i=0;i<m;i++)printf("%4d",i);printf("\n");for(i=0;i<n;i++){printf("%d\t",i);for(j=0;j<m;j++)printf("%4d",osPoint->map[i][j]);printf("\n");}printf("\n");printf("--------------------------------------------------------------\n\n");return 0;}/*-------------盘块一致性检查------------------------*/int checkdisk(void){int sum[n][m];int i,j;int unnormal=0; //用于记录一致性状况不良的盘块个数//将位示图与数据计数器求和用于检查两者是否互补for(i=0;i<n;i++)for(j=0;j<m;j++)sum[i][j]=osPoint->map[i][j]+osPoint->check[i][j];//输出检查数组printf("\n");printf("\t");for(i=0;i<m;i++)printf("%4d",i);printf("\n");for(i=0;i<n;i++){printf("%d\t",i);for(j=0;j<m;j++)printf("%4d",sum[i][j]);printf("\n");}printf("\n");//判断一致性状态并修改对应数组或报错for(i=0;i<n;i++)for(j=0;j<m;j++)if(sum[i][j]!=1){unnormal++;int z=i*16+j;if(sum[i][j]==0){osPoint->map[i][j]=1;printf("%d此盘块应为空闲\n",z);}if(sum[i][j]>=2){if(osPoint->map[i][j]==sum[i][j]-1){osPoint->map[i][j]=0;printf("%d此盘块应以分配\n",z);}else if(osPoint->map[i][j]<sum[i][j]-1){printf("!!警告!!%d此盘块被分配多次!!\n",z);}}}// 如果unnormal=0则所有盘块正常if(unnormal==0)printf("系统正常!盘块一致性良好!!\n");printf("--------------------------------------------------------------\n\n");return 0;}int main(){/*********************************************************************/ printf("-----Welcome To My Operate System Of File(FAT)-----\n");//使用说明书printf("\n 以下是使用说明书:\n");printf("--------------------------------------------------------------\n");printf("|| format :对磁盘格式化. || \n");printf("|| exit :安全退出该文件系统,保存信息. || \n");printf("|| mkdir dirname :创建子目录. || \n");printf("|| rmdir dirname :删除子目录. || \n");printf("|| ls dirname :显示当前目录下信息. || \n");printf("|| cd dirname :更改当前目录. || \n");printf("|| create filename :创建一个新文件,并且打开. || \n");printf("|| write filename :选择一个打开的文件写入信息|| \n");printf("|| read filename :选择一个打开的文件读取信息. || \n");printf("|| rm filename :删除文件. || \n");printf("|| open filename :打开文件. || \n");printf("|| close filename :关闭文件. || \n");printf("|| display:显示位示图|| \n");printf("|| check:数据一致性检查|| \n");printf("|| || \n");printf("|| || \n");printf("-------------------------------------------------------------\n\n");//创建用户文件打开表openlist=new OPENLIST;//申请虚拟空间并且初始化BaseAddr=(char *)malloc(DiskSize);//虚拟磁盘初始化osPoint=(struct DISK *)(BaseAddr);//加载磁盘文件if((fp=fopen(FilePath,"r"))!=NULL){fread(BaseAddr,sizeof(char),DiskSize,fp);printf("加载磁盘文件( %s )成功,现在可以进行操作了!\n\n",FilePath); }else{printf("这是你第一次使用该文件管理系统!\t正在初始化...\n"); format();printf("初始化已经完成,现在可以进行操作了!\n\n");}printf("--------------------------------------------------------------\n\n");while(1){cout<<currentPath;cin>>cmd;if(cmd=="format"){format();}else if(cmd=="mkdir"){cin>>command;mkdir(command);}else if(cmd=="rmdir"){cin>>command;rmdir(command);}else if(cmd=="ls"){listshow();else if(cmd=="cd") {cin>>command; changePath(command);}else if(cmd=="create") {cin>>command; create(command);}else if(cmd=="write") {cin>>command;write(command);}else if(cmd=="read") {cin>>command;read(command);}else if(cmd=="rm") {cin>>command; delfile(command);}else if(cmd=="open") {cin>>command;open(command);}else if(cmd=="close") {cin>>command;close(command);}else if(cmd=="exit"){exit();break;}else if(cmd=="display"){display();}else if(cmd=="check"){checkdisk();}else cout<<"无效指令,请重新输入:"<<endl; }printf("Thank you for using my file system!\n"); }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
空闲磁盘存储的管理:位示图法
1:建立相应的数据结构
2:磁盘上建立一个文件,文件长度设为10MB,为该文件来模拟一个磁盘,磁盘的物理块大小为512字节
3:显示每次磁盘的请求和空间释放后的位示图状态
4显示每次磁盘的请求和空间释放后的全磁盘的状态
5:模拟文件的创建和删除,从而产生磁盘潘快请求和释放,验证以上设计
代码:
// OS暑?期ú课?程ì设Θ?计?.cpp : 定¨义?控?制??应畖用?程ì序ò的?入?口ú点?。
£
//
#include"stdafx.h"
#include<iostream>
#include<string>
#include<math.h>
using namespace std ;
//文?件t类え?
class file
{
public:
string name ;
int occupy ;
int grade_block ;
int start ;
};
#define MAX_LINE 3
#define MAX_COLUMN 32
int BIT[32][1000];
int byte[MAX_LINE] ;
int file_count;
int judge[32] ;
int judge2[32];
int cycle ;
file f[1000];
void init(int line ,int column);
void show() ;
void set(int now_location, int occupy );
void clear(int now_location, int occupy);
void bitset(int index ,int temp_block_quantity);
void create_file(string temp_name, int temp_occupy );
void delete_file(string name);
bool byte_judge(int num,int i);
int _tmain(int argc, _TCHAR* argv[])
{
string cmd;
string file_name ;
int file_occupy ;
init( MAX_LINE, MAX_COLUMN ) ; //初?始?化ˉwhile ( cin >> cmd ) //
{
if( "q" == cmd || "Q" == cmd )
{
exit(0) ;
return 0 ;
}
cin >> file_name ;
if("create" == cmd)
{
cin >>file_occupy ;
create_file(file_name,file_occupy);
}
else
{
delete_file(file_name) ;
}
}
return 0;
}
void show()
{
for(int i = 0 ; i < MAX_LINE ; i ++)
{
for(int j = 0 ; j < MAX_COLUMN ; j ++)
{
//cout<<BIT[i][j] <<" ";
cout<<byte_judge(byte[i],j)<<" ";
}
cout<< endl ;
}
}
void set(int now_location, int occupy )
{
int line ;
int column ;
for(int i = 0 ; i < occupy ; i ++ )
{
line = (now_location - i) / MAX_COLUMN ;
column = (now_location - i ) % MAX_COLUMN ;
//BIT[line][column] = 1 ;
byte[line] |= judge[column];
}
}
//清?零?
void clear(int now_location, int occupy)
{
int line ;
int column ;
for(int i = 0 ; i < occupy ; i ++)
{
line = (now_location + i) / MAX_COLUMN ;
column = (now_location + i ) % MAX_COLUMN ;
//BIT[line][column] = 0 ;
byte[line] &= judge2[column];
}
}
void bitset(int index ,int temp_block_quantity)
{
int block_quantity = temp_block_quantity ;
int free_quantity = 0 ;
int line, column ;
int sign = cycle - 1 ;
for (;; cycle++ )
{
line = cycle / MAX_COLUMN ;
column = cycle % MAX_COLUMN ;
if( 0 == byte_judge(byte[line],column))
{
free_quantity ++ ;
}
else
{
free_quantity = 0 ;
}
if(free_quantity >= block_quantity )
{
f[index].start = cycle - block_quantity + 1;
set(cycle, block_quantity);
cycle ++;
cout<<"create file success"<<endl;
show();
return ;
}
if(cycle >= MAX_LINE * MAX_COLUMN-1)
{
cycle = -1;
free_quantity = 0;
}
if(sign == cycle )
{
break ;
}
}
cout<<"error: create file fail"<<endl;
}
void create_file(string temp_name, int temp_occupy )
{
int block_quantity ;
f[file_count].name = temp_name ;
block_quantity = temp_occupy / 512 + 1 ;
f[file_count].occupy=block_quantity ;
bitset(file_count ,block_quantity );
file_count ++ ;
}
//删?除y文?件t
void delete_file(string name)
{
for(int i = 0 ; i < file_count ; i ++)
{
if(name == f[i].name)
{
clear(f[i].start,f[i].occupy);
for(int j = i; j < file_count - 1; j ++)
{
f[j] = f[ j + 1 ];
}
file_count -- ;
cout<<"delete file success"<<endl;
show();
return ;
}
}
cout<<"ERROR THE FILE NOT EXIST"<< endl ;
}
//初?始?化ˉ
void init(int line ,int column)
{
int con = 1 ;
file_count = 0 ;
cycle = 0 ;
for(int i = 0; i < 32 ; i ++)
{
judge[i] = con ;
judge2[i]=judge[i];
judge2[i] ^= 0xffffffff;
con*=2;
}
for(int i =0 ; i<MAX_LINE ; i++)
byte[i]= 0;
}
bool byte_judge(int num,int i)
{
bool result ;
result = num & judge[i];
return result;
}。