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

目录

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_cow_num; j++){
            if (i*map_cow_num + j<K)
                bitMap[i][j] = 1;      //K个保留区
            else
                bitMap[i][j] = 0;      //其余区域空闲
        }//for
    }//for
}//Init

3.3 目录

我们的文件系统中仅设置一个目录,该目录包含文件系统中的所有文件。除了不需要显示地创建和删除之外,目录在很多方面和普通文件相像。目录对应0号文件描述符。初始状态下,目录中没有文件,所有,目录对应的描述符中记录的长度应为0,而且也没有分配磁盘块。每创建一个文件,目录文件的长度便增加一分。目录文件的内容由一系列的目录项组成,其中每个目录项由如下内容组成:

• 文件名

• 文件描述符序号

显示目录

/**
 * 函数名:show_Menu
 * 函数功能:提示菜单选项
 */
void show_Menu(){
    printf("==================菜单===================\n");
    printf("**   1.新建文件\n");
    printf("**   2.查看文件列表\n");
    printf("**   3.查看位图信息\n");
    printf("**   4.查看硬盘使用情况\n");
    printf("**   5.删除文件\n");
    printf("**   6.打开文件\n");
    printf("**   7.关闭文件\n");
    printf("**   8.移动文件\n");
    printf("**   9.查看文件内容\n");
    printf("**   10.修改文件内容\n");
    printf("**   11.查看文件详细信息\n");
    printf("**   0.退出\n");
    printf("=========================================\n");
}

3.4 文件的创建与删除

创建文件时需要进行如下操作;

• 找一个空闲文件描述符(扫描ldisk [0]~ldisk [k - 1])

• 在文件目录里为新创建的文件分配一个目录项(可能需要为目录文件分配新的磁盘块)

• 在分配到的目录项里记录文件名及描述符编号.

• 返回状态信息(如有无错误发生等)

删除文件时需要进行如下操作(假设文件没有被打开):

• 在目录里搜索该文件的描述符编号

• 删除该文件对应的目录项并更新位图

• 释放文件描述符

• 返回状态信息

创建

/**
 * 函数名:create
 * 函数功能:根据指定的文件名创建新文件
 * @param filename
 * @return
 */
int create(char *filename){
    /*查询该文件是否存在*/
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            printf("该文件已存在!\n");
            return ERROR;            //文件存在
        }
    }
    /*文件不存在,更新Directorys值*/
    int sub,i,j;
    //搜索文件列表,碰到第一个index=-1的值
    for (i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == -1){
            //Directorys[i]
            sub = i;    //找到一个可以用的位置
            break;
        }
        else if (i == maxDirectoryNumber){
            printf("空间不足!");
            return ERROR;
        }
    }
    /*为sub目录项赋值*/
    strcpy(Directorys[sub].fileName, filename);
    //更新index
    for (i = 1; i <= maxDirectoryNumber; i++){
        if (!isExist(i)){       //如果不存在编号为i的index值
            Directorys[sub].index = i;   //更新index值
            break;                    //更新结束
        }
    }
    /*输入目录项其他项*/
    printf("文件大小 (< 61*512 Byte):");
    scanf("%d", &Directorys[sub].fileDescriptor.fileLength);
    //计算需要空间块数量,用于判断剩余空间是否满足要求
    int L_Counter;
    if (Directorys[sub].fileDescriptor.fileLength%B){
        L_Counter = Directorys[sub].fileDescriptor.fileLength / B + 1;
    }
    else{
        L_Counter = Directorys[sub].fileDescriptor.fileLength / B;
    }
    //查位示图,找到没使用的位置
    for (i = K; i<map_row_num*map_cow_num - L_Counter; i++){
        int outflag = 0;//标记位,用于跳出外循环
        //查找连续的L_Counter块bitMap空间块
        for (int j = 0; j<L_Counter; j++){
            int maprow = (i + j) / map_cow_num;
            int mapcow = (i + j) % map_cow_num;
            if (bitMap[maprow][mapcow]){//如果位图某块不空闲
                break;//进入外循环继续查找
            }
            else{//位图空闲
                if (j == L_Counter - 1){
                    outflag = 1;//找到可用块,可以跳出查找
                }
            }
        }//for
        if (outflag == 1){
            //为块数组赋值,保存数据
            Directorys[sub].fileDescriptor.file_block_length = L_Counter;
            //    printf("L_Counter=%d\n",L_Counter);
            Directorys[sub].fileDescriptor.beginpos = i;//i为起始位置(起始块号)
            for (j = 0; j<L_Counter; j++){               //数组记录占用的块号
                Directorys[sub].fileDescriptor.file_allocation_blocknumber[j] = i + j;
            }
            //初始化其他项(应该可以省略)
            Directorys[sub].isOpenFlag = 0;
            Directorys[sub].fileDescriptor.rwpointer = 0;
            memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
            break;
        }
        else if (L_Counter + i == map_row_num*map_cow_num - 1 - K){
            printf("空间不足...x\n");
            Directorys[sub].index = -1;
            return ERROR;
        }
    }//for
    int map_ = i;
    printf(" %s create success!\n", filename);
    /*更新位示图*/
    for (int j = 0; j<Directorys[sub].fileDescriptor.file_block_length; j++){//从i开始更新file_block_length的数据
        int maprow = (map_ + j) / map_cow_num;
        int mapcow = (map_ + j) % map_cow_num;
        bitMap[maprow][mapcow] = 1;
    }//for
    
    /*文件建立结束*/
    Directorys[0].count++;          //更新文件数量
    return OK;
}

删除

/**
 * 函数名:destroy
 * 函数功能:根据文件名删除文件
 * @param filename
 * @return
 */
int destroy(char *filename){
    int sub,i;
    for (i = 1; i <= maxDirectoryNumber; i++){//不是顺序的
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到该文件
        }
        else if (i == maxDirectoryNumber){
            printf("文件不存在!\n");
            return ERROR;           //搜索结束,未找到对应文件名
        }
    }
    //    printf("%d\n",sub);
    //删除操作
    if (Directorys[sub].isOpenFlag){
        printf("文件已打开,不可删除,请关闭后删除!\n");
        return ERROR;
    }
    /*更新位示图信息*/
    //位示图为一个二维数组,记录的是磁盘块的横坐标值,表示该块磁盘是否空闲
    int position = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];   //起始磁盘号
    for (i = 0; i < Directorys[sub].fileDescriptor.file_block_length; i++){
        int d_row = (position + i) / map_row_num;
        int d_cow = (position + i) % map_row_num;
        bitMap[d_row][d_cow] = 0;
    }//赋值空闲
    
    //更新Directorys[sub]信息
    memset(Directorys[sub].fileName, '\0', File_Name_Length);//文件名初始化
    Directorys[sub].index = -1;          //初始化文件描述符序号为-1
    /*配置文件描述符的相关项*/
    memset(Directorys[sub].fileDescriptor.file_allocation_blocknumber, -1, File_Block_Length);
    //初始化磁盘号数组为-1
    Directorys[sub].fileDescriptor.file_block_length = 0;    //初始化实际分配的磁盘号数组长度为0
    Directorys[sub].fileDescriptor.fileLength = 0;           //初始化文件长度为0
    Directorys[sub].fileDescriptor.beginpos = 0;             //初始化文件初始位置为0
    memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
    Directorys[sub].fileDescriptor.rwpointer = 0;            //初始化读写指针
    
    printf(" %s 删除成功!\n", filename);
    /*文件数量处理*/
    Directorys[0].count--;
    return OK;
}

3.5 文件的打开与关闭

文件系统维护一张打开文件表.打开文件表的长度固定,其表目包含如下信息:

• 读写缓冲区

• 读写指针

• 文件描述符号

文件被打开时,便在打开文件表中为其分配一个表目;文件被关闭时,其对应的表目被释放。读写缓冲区的大小等于一个磁盘存储块。打开文件时需要进行的操作如下:

• 搜索目录找到文件对应的描述符编号

• 在打开文件表中分配一个表目

• 在分配到的表目中把读写指针置为0,并记录描述符编号

• 读入文件的第一块到读写缓冲区中

• 返回分配到的表目在打开文件表中的索引号

关闭文件时需要进行的操作如下:

• 把缓冲区的内容写入磁盘

• 释放该文件在打开文件表中对应的表目

• 返回状态信息

打开

/**
 * 函数名:open
 * 函数功能:根据文件名打开文件。该函数返回的索引号可用于后续的read, write, lseek, 或close 操作
 * @param filename
 * @return
 */
int open(char *filename){
    int sub;
    //查询所有的目录项
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到该文件
        }
        else if (i == maxDirectoryNumber){
            return ERROR;           //搜索结束,未找到对应文件名
        }
    }
    Directorys[sub].isOpenFlag = 1;      //打开文件标志
    return OK;
}//open

关闭

/**
 * 函数名:close
 * 函数功能:根据打开目录索引号关闭指定文件
 * @param index
 * @return
 */
int close(int index){
    int sub;                               //下角标,表示Directorys[sub]
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == index){
            sub = i;
            if (!Directorys[i].isOpenFlag){
                printf("文件关闭!\n");
            }
            break;                          //找到
        }
        else if (i == maxDirectoryNumber){                     //是否为最后一个查询的数据
            printf("索引信息有误\n");
            return ERROR;                   //index 数据有错误,找不到该索引
        }
    }//for
    //把缓冲区的内容写入磁盘
    int pos = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];//纵坐标的起始位置
    for (int i = 0; i<Directorys[sub].fileDescriptor.fileLength; i++){
        int L_Pos = i / B;
        int B_Pos = i % B;
        ldisk[pos + L_Pos][B_Pos] = Directorys[sub].fileDescriptor.RWBuffer[i];
    }
    //释放该文件在打开文件表中对应的表目
    Directorys[sub].isOpenFlag = 0;  //释放,标志位置零
    Directorys[sub].fileDescriptor.rwpointer = 0;//读写指针清除
    //返回状态信息
    return OK;
}//close

3.6 读写

文件打开之后才能进行读写操作.读操作需要完成的任务如下:

1. 计算读写指针对应的位置在读写缓冲区中的偏移

2. 把缓冲区中的内容拷贝到指定的内存位置,直到发生下列事件之一:

• 到达文件尾或者已经拷贝了指定的字节数。这时,更新读写指针并返回相应信息

• 到达缓冲区末尾。这时,把缓冲区内容写入磁盘,然后把文件下一块的内容读入磁盘。最后返回第2步。

/**
 * 函数名:read
 * 函数功能:从指定文件顺序读入count 个字节memarea 指定的内存位置。读操作从文件的读写指针指示的位置开始
 * @param index
 * @param mem_area
 * @param count
 * @return
 */
int read(int index, char memory_area[], int count){
    int sub = isExist(index);
    if (sub == ERROR){
        printf("索引信息有误 !\n");
        return ERROR;
    }
    /*找到文件*/
    /*打开文件进行操作*/
    if (!Directorys[sub].isOpenFlag){
        open(Directorys[sub].fileName);
    }
    /*读ldisk内容并复制到memory_area[]中*/
    int step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];
    //L的起始位置
    int step_ = Directorys[sub].fileDescriptor.file_block_length - 1;     //记录要拷贝块的数量
    /*将文件以B为大小划分后拷贝给mem_area[]*/
    int pos = 0;
    for (int i = 0; i<step_; i++){
        load(step_L, B, pos, memory_area);
        pos += B;
        step_L++;
    }
    /*拷贝ldisk[][]最后一块数据*/
    int strLen = Directorys[sub].fileDescriptor.fileLength - (B*step_);
    load(step_L, strLen, pos, memory_area);
    //printf("文件:%c\n", memory_area[1]);
    //注:分配的文件大小不是真正拷贝的文件大小
    return OK;
}

/**
 * 函数名:write
 * 函数功能:把memarea 指定的内存位置开始的count 个字节顺序写入指定文件。写操作从文件的读写指针指示的位置开始
 * @param index
 * @param mem_area
 * @param count
 * @return
 */
int write(int index, char memory_area[], int count){
    /*根据index找到文件*/
    int sub = isExist(index);
    if (sub == ERROR){
        printf("索引信息有误!\n");
        return ERROR;
    }
    /*找到文件*/
    /*打开文件进行操作*/
    if (!Directorys[sub].isOpenFlag){
        open(Directorys[sub].fileName);
    }
    /*读入要写的内容*/
    int i = 0;
    int step_ = 0;//file_allocation_blocknumber[]下标计数器
    int num = 0;//RWBuffer[]读写次数计数器
    int step_L;
    int step_B;
    int COUNT = count;
    while (count){
        Directorys[sub].fileDescriptor.RWBuffer[i] = memory_area[COUNT - count];
        count--;//count计数递减
        i++;//计数+1
        if (i == Buffer_Length){
            int step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[step_];
            //列坐标
            int step_B = Buffer_Length * num;
            save(step_L, step_B, Buffer_Length, sub);//复制完成
            num++;
            if (num == B / Buffer_Length){//写完一行,进入下一行
                num = 0;
                step_++;
            }
            i = 0;
            //
        }
        if (count == 0){
            step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[step_];
            step_B = Buffer_Length * num;
            save(step_L, step_B, i, sub);
            break;
        }
    }//while
    memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
    return OK;
}

3.7 文件列表

/**
 * 函数名:directory
 * 函数功能:列表显示所有文件及其长度
 */
void directory(){
    if (Directorys[0].count == 0) {
        printf("无文件\n");
    }
    for (int i = 1; i <= Directorys[0].count; i++){
        if (Directorys[i].index != -1){            //index值有效的文件输出
            printf(" %d :%s\t\t", i, Directorys[i].fileName);
            printf("大小:%d Byte\n", Directorys[i].fileDescriptor.fileLength);
        }//
    }
}//directory

3.8磁盘信息显示

/**
 * 函数名:show_ldisk
 * 函数功能:显示磁盘信息
 */
void show_ldisk(){
    for (int i = 0; i<L; i++){
        printf("%d:", i);
        printf("%s\n", ldisk[i]);
    }
    printf("\n");
}

3.9文件详细信息查看

/**
 * 函数名:show_File
 * 函数功能:显示文件信息
 * @param filename
 * @return
 */
int show_File(char *filename){
    int sub;
    //查询所有的目录项
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到该文件
        }
        else if (i == maxDirectoryNumber){
            return ERROR;           //搜索结束,未找到对应文件名
        }
    }
    printf("文件名:%s\n", Directorys[sub].fileName);
    printf("是否打开 (Y:0 N:1):%d\n", Directorys[sub].isOpenFlag);
    //printf("index: %d\n", Directorys[sub].index);
    printf("大小:%d Byte\n", Directorys[sub].fileDescriptor.fileLength);
    return OK;
}

3.10位图信息

/**
 * 函数名:show_bitMap
 * 函数功能:显示位图信息
 */
void show_bitMap(){
    for (int i = 0; i<map_row_num; i++){
        for (int j = 0; j<map_cow_num; j++){
            printf("%d  ", bitMap[i][j]);
        }
        printf("\n");
    }//for
}//show_bitMap

3.11文件移动

/**
 * 函数名:lseek
 * 函数功能:把文件的读写指针移动到pos 指定的位置
 * @param index
 * @param pos
 * @return
 */
int lseek(int index, int position){
    //先找到index代表的数据项
    int sub;                               //下角标,表示Directorys[sub]
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == index){
            sub = i;
            break;                          //找到
        }
        else if (i == maxDirectoryNumber){                  //是否为最后一个查询的数据
            printf("索引信息有误!\n");
            return ERROR;                   //index 数据有错误,找不到该索引
        }
    }//for
    //找到index对应的元素后,把文件的读写指针移动到position 指定的位置
    Directorys[sub].fileDescriptor.rwpointer = position;
    return OK;                              //处理成功
}//lseek

测试

为了能够对我们的模拟系统进行测试,请编写一个操纵文件系统的外壳程序或者一个菜单驱动系统。

4.1 菜单

4.2 新建文件

文件不存在

文件存在时

4.3 查看文件列表

4.4 查看位图信息

保存文件前

保存3个文件后

4.5 打开/关闭文件

打开文件 1.txt 与文件 2.txt

关闭文件 2.txt

4.6 删除文件

若文件已打开,则不可删除

若文件处于关闭状态,则顺利删除

删除成功

4.7 移动文件

4.8 查看/修改文件内容

查看文件 1.txt :无内容

修改文件 1.txt :

若大于文件大小,则不保存

查看文件 1.txt :无保存的内容

若小于文件大小,则保存成功

再次查看文件 1.txt :有保存的内容

4.9 查看文件详情

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

使用情况截图(部分)

5 总结 

在这次设计中,我对于文件属性,文件命名,文件操作,文件存取方式有了更加深刻的理解,其中令我印象最为深刻的是文件目录的管理。其中的文件控制块跟索引节点起到了非常重要的作用。文件控制块中包含了有关文件存取控制的信息,文件结构的信息,文件使用的信息,文件管理的信息。查找文件时,根据文件名找到文件控制块,再通过控制块获得相应的信息。

为了减少检索文件访问的物理快熟,文件系统把文件目录项中的文件名和其他管理信息分开。后者单独组成定长的一个数据结构,称为索引节点。

本次实验时间较短,有诸多不完善之处,未来有时间讲进行总结及完善,另外还需要多借鉴他人文件系统的整体设计方式和思想,对文件系统有了一个比较全面深刻的认识。

【实验目的】 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、付费专栏及课程。

余额充值