操作系统实验——文件操作系统

本文详细介绍了一个基于模拟I/O系统的简易文件系统的设计与实现过程,涵盖了文件创建、删除、读写、目录管理等核心功能,同时提供了测试案例与总结反思。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 实验简介

2 I/O系统

相关参数与数据结构

3 文件系统

3.1 用户与文件系统之间的接口

3.2 文件系统的组织

初始化

3.3 目录

显示目录

3.4 文件的创建与删除

创建

删除

3.5 文件的打开与关闭

打开

关闭

3.6 读写

3.7 文件列表

3.8磁盘信息显示

3.9文件详细信息查看

3.10位图信息

3.11文件移动

4 测试

4.1 菜单

4.2 新建文件

4.3 查看文件列表

4.4 查看位图信息

4.5 打开/关闭文件

4.6 删除文件

4.7 移动文件

4.8 查看/修改文件内容

4.9 查看文件详情

4.10 查看磁盘存储情况(512*64)

5 总结 


实验简介

本实验要求在模拟的I/O系统之上开发一个简单的文件系统。用户通过create, open, read等命令与文件系统交互。文件系统把磁盘视为顺序编号的逻辑块序列,逻辑块的编号为0至1。I/O系统利用内存中的数组模拟磁盘。

2 I/O系统

实际物理磁盘的结构是多维的:有柱面、磁头、扇区等概念。I/O系统的任务是隐藏磁盘的结构细节,把磁盘以逻辑块的面目呈现给文件系统。逻辑块顺序编号,编号取值范围为0至L1,其中L表示磁盘的存储块总数。实验中,我们可以利用数组ldisk[C][H][B]构建磁盘模型,其中CHB分别表示柱面号,磁头号和扇区号。每个扇区大小为512字节。I/O系统从文件系统接收命令,根据命令指定的逻辑块号把磁盘块的内容读入命令指定的内存区域,或者把命令指定的内存区域内容写入磁盘块。文件系统和I/O系统之间的接口由如下两个函数定义:

• read_block(int i, char *p);

该函数把逻辑块i的内容读入到指针p指向的内存位置,拷贝的字符个数为存储块的长度B

• write block(int i, char *p);

该函数把指针p指向的内容写入逻辑块i,拷贝的字符个数为存储块的长度B。此外,为了方便测试,我们还需要实现另外两个函数:一个用来把数组ldisk 存储到文件;另一个用来把文件内容恢复到数组。

相关参数与数据结构

//磁盘总大小为512*64
#define B        512       			//定义存储块的长度B字节
#define L        64        			//定义磁盘的存储块总数L,逻辑号0-(L-1)
#define K        3      			//磁盘的前k 个块是保留区

#define OK       1     				//操作成功
#define ERROR    0    				//操作错误

#define File_Block_Length    (B-3)  //定义文件磁盘块号数组长度
#define File_Name_Length     (B-1)  //定义文件名的长度

//8*8共表示64个逻辑块,即磁盘的总块数:L
#define map_row_num     8           //位图的行数
#define map_cow_num     8           //位图的列数

#define maxDirectoryNumber  49      //定义目录中目录项(文件数量)的最大值

#define Buffer_Length 64            //定义读写缓冲区的大小,用于打开文件表项

typedef struct FileDescriptor{//文件描述符
	int fileLength;                                        //文件长度。单位:字节
	int file_allocation_blocknumber[File_Block_Length];    //文件分配到的磁盘块号数组
	int file_block_length;                                 //文件分配到的磁盘块号数组实际长度
	int beginpos;                                          //文件的起始坐标位置beginpos=map_cow_num*row + cow
	int rwpointer;                                         //读写指针:初始化为0,随着RWBuffer变化
	char RWBuffer[Buffer_Length];                          //读写缓冲区,存文件的内容
}FileDescriptor;

typedef struct Directory{//目录项,此处仅代表文件

	int  index;                     						//文件描述符序号
	int  count;                     						//用于目录中记录文件的数量
	char fileName[File_Name_Length];						//文件名
	int  isFileFlag;                						//判断是文件和是目录,1为文件,0为目录
	int  isOpenFlag;                						//判断文件是否打开,1为打开,0为关闭
	FileDescriptor fileDescriptor;  						//文件描述符信息,与index 对应
}Directory;


char ldisk[L][B];											//构建磁盘模型

char memory_area[L*(B - K)];								//定义一个足够长的字符数组
char mem_area[L*(B - K)] = { '\0' };
Directory Directorys[maxDirectoryNumber + 1];				//包括目录在内,共有目录项maxDirectoryNumber+1,Directorys[0]保存目录
int bitMap[map_row_num][map_cow_num];						// 0:磁盘块空闲;1:磁盘块使用

文件系统

文件系统位于I/O系统之上。

3.1 用户与文件系统之间的接口

文件系统需提供如下函数;create, destroy, open, read, write。

• create(filename): 根据指定的文件名创建新文件。

• destroy(filename): 删除指定文件。

• open(filename): 打开文件。该函数返回的索引号可用于后续的read, write, lseek,或close操作。

• close(index): 关闭制定文件。

• read(index, mem_area, count): 从指定文件顺序读入count个字节memarea指定的内存位置。读操作从文件的读写指针指示的位置开始。

• write(index, mem_area, count): 把memarea指定的内存位置开始的count个字节顺序写入指定文件。写操作从文件的读写指针指示的位置开始。

• lseek(index, pos): 把文件的读写指针移动到pos指定的位置。pos是一个整数,表示从文件开始位置的偏移量。文件打开时,读写指针自动设置为0。每次读写操作之后,它指向最后被访问的字节的下一个位置。lseek能够在不进行读写操作的情况下改变读写指针能位置。

• directory: 列表显示所有文件及其长度。

3.2 文件系统的组织

磁盘的前k个块是保留区,其中包含如下信息:位图和文件描述符。位图用来描述磁盘块的分配情况。位图中的每一位对应一个逻辑块。创建或者删除文件,以及文件的长度发生变化时,文件系统都需要进行位图操作。前k个块的剩余部分包含一组文件描述符。每个文件描述符包含如下信息:

• 文件长度,单位字节

• 文件分配到的磁盘块号数组。该数组的长度是一个系统参数。在实验中我们可以把它设置为一个比较小的数,例如3。

初始化

/**
 * 函数名:Init
 * 函数功能:初始化文件系统:初始化位图(0表示空闲,1表示被占用);初始化0号文件描述符;
 */
void Init(){
    int i, j;//两个计数量
    /*初始化磁盘*/
    for (i = 0; i<L; i++){
        for (j = 0; j<B; j++){
            ldisk[i][j] = '\0';//初始化为空
        }
    }
    /*初始化目录项*/
    for (i = 0; i <= maxDirectoryNumber; i++){
        for (j = 0; j<File_Name_Length; j++){
            Directorys[i].fileName[j] = '\0';    //初始化名字为'\0'
        }
        
        if (i == 0){//第一个为目录
            Directorys[i].index = 0;                //目录文件描述符序号为0
            Directorys[i].isFileFlag = 0;
            Directorys[i].count = 0;
        }
        else{//其他均表示文件
            Directorys[i].index = -1;          //初始化文件描述符序号为-1
            Directorys[i].count = -1;           //其他文件项不记录count值
            Directorys[i].isFileFlag = 1;       //初始化其他目录项均为文件
            Directorys[i].isOpenFlag = 0;       //文件均关闭
            /*配置文件描述符的相关项*/
            
            memset(Directorys[i].fileDescriptor.file_allocation_blocknumber, -1, File_Block_Length);
            //初始化磁盘号数组为-1
            Directorys[i].fileDescriptor.file_block_length = 0;    //初始化实际分配的磁盘号数组长度为0
            Directorys[i].fileDescriptor.fileLength = 0;           //初始化文件长度为0
            Directorys[i].fileDescriptor.beginpos = 0;             //初始化文件初始位置为0
            for (j = 0; j<Buffer_Length; j++){
                Directorys[i].fileDescriptor.RWBuffer[j] = '\0';   //初始化读写缓存为'\0'
            }
            Directorys[i].fileDescriptor.rwpointer = 0;            //初始化读写指针
        }
    }//for
    /*初始化位示图,均初始化为空闲*/
    for (i = 0; i<map_row_num; i++){
        for (j = 0; j<map_co
实验目的】 1. 了解文件系统的原理; 2. 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 【实验准备】 1.文件的逻辑结构  顺序文件  索引文件  索引顺序文件  直接文件和哈希文件 2.外存分配方式  连续分配  链接分配  索引分配 【实验内容】 1. 实验要求 要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 2. 实验题目  设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。  程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。  为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 因系统小,文件目录的检索使用了简单的线性搜索。文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。程序中使用的主要设计结构如下:主文件目录和用户文件目录( MFD、UFD)打开文件目录( AFD)(即运行文件目录)。 M D F 用户名 文件目录指针 用户名 文件目录指针 U F D 文件名 保护码 文件长度 文件名 A F D 打开文件打开保护码 读写指针
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值