操作系统实验五文件系统16281028

 

 

实验五 文件系统

1 实验简介

2 I/O系统

3 文件系统

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

3.2 文件系统的组织

3.3 目录

3.4 文件的创建与删除

3.5 文件的打开与关闭

3.6 读写

4 测试

4.1 数据结构

4.2 创建文件

4.3 文件删除

4.4 文件打开

4.5 文件关闭

5 实验结果

6 实验分析


实验五 文件系统

1 实验简介

本实验要求在模拟的I/O系统之上开发一个简单的文件系统。用户通过create, open, read等命令与文件系统交互。文件系统把磁盘视为顺序编号的逻辑块序列,逻辑块的编号为0至L  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 存储到文件;另一个用来把文件内容恢复到数组。

3 文件系统

文件系统位于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。

3.3 目录

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

 文件名

 文件描述符序号

3.4 文件的创建与删除

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

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

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

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

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

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

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

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

 释放文件描述符

 返回状态信息

3.5 文件的打开与关闭

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

 读写缓冲区

 读写指针

 文件描述符号

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

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

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

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

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

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

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

 把缓冲区的内容写入磁盘

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

 返回状态信息

3.6 读写

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

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

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

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

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

其他操作请同学们自己考虑。

4 测试

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

4.1 数据结构

typedef struct files
{
    int number;//文件编号
    char *filename;//文件名
    int size;//文件大小
    int pos;//文件偏移指针
    INDIRECT *addr[3];//3个直接地址
    char *content;//存放文件中的所有内容
}FILES;

4.2 创建文件

int create(char *filename)
{
    DIC *dic = dicHead;
    int flag = 0;
    for(int i = 0; i < countOfFiles; i ++)
    {
        if(strcmp(dic->filename, filename) == 0)
        {
            flag = 1;
            break;
        }
        dic = dic->next;
    }

    if(flag == 1)
    {
        printf("文件名已存在!\n");
        return NULL;
    }
    int a = M;
    int start = K;
    int size = L - K;
    countOfFiles ++;
    // 生成随机数
    int blockNumber = createRandomNUmber(start, size);
    // 查询位图
    while(map[blockNumber / a][blockNumber % a] == 1)
	{
        blockNumber = createRandomNUmber(start, size);
	}
    // 置位图为1
    map[blockNumber / a][blockNumber % a] = 1;
    // 建立目录
    createDirectory(filename, blockNumber);
	printf("成功创建!\n");
	return 0;
}

4.3 文件删除

int destroy(char *filename)
{
    DIC *dic = dicHead;
    int flag = 0;
    for(int i = 0; i < countOfFiles; i ++)
    {
        if(strcmp(dic->filename, filename) == 0)
        {
            flag = 1;
            break;
        }
        dic = dic->next;
    }
    if(flag == 0)
    {
        printf("文件不存在!\n");
        return -1;
    }
    //删除文件
    int blockNumber = dic->index1->size / SIZE;
	if(dic->index1->size % SIZE > 0)
	{
        blockNumber ++;
	}
    //删除所有块里的元素
    for(int i = 0; i < blockNumber; i ++)
    {
        write_block(dic->index1->addr[i]->diskNum, "\0");
    }
    //删除目录
    destoryDirectory(filename);
	countOfFiles --;
	printf("成功删除!\n");
    return 0;
}

4.4 文件打开

FILES *open(char *filename)
{
    DIC *dic = dicHead;
	// 缓冲区
    char buffer[512] = "";
	int flag = 0;
	for(int i = 0; i < countOfFiles; i ++){
        if(strcmp(dic->filename, filename) == 0){
            flag = 1;
            break;
        }
        dic = dic->next;
    }

    if(flag == 0){
        printf("文件不存在!\n");
        return NULL;
    }
	// 打开文件
    FILES *file = NULL;
	file = (FILES *)malloc(sizeof(FILES));
	file->number = dic->index1->number;
	for(int i = 0; i < 3; i ++){
        file->addr[i] = (INDIRECT *)malloc(sizeof(INDIRECT));
	}
    for(int i = 0; i < 3; i ++){
        memcpy(file->addr[i], dic->index1->addr[i], sizeof(INDIRECT));
	}
    file->size = dic->index1->size;
	file->filename = (char *)malloc(strlen(filename) * sizeof(char));
	memcpy(file->filename, filename, strlen(filename));
	file->pos = 0;
	//将磁盘中的内容读到file中
	int block = file->size / SIZE;
	int offset = file->size % SIZE;
	file->content = (char *)malloc(file->size * sizeof(char));
	if(offset > 0)
	{
        block ++;
    }
	for(int i = 0; i < block; i ++){
        read_block(dic->index1->addr[i]->diskNum, buffer);
		strcpy(&file->content[i * SIZE], buffer);
    }
    return file;
}

4.5 文件关闭

int close(FILES *file)
{
    for(int i = 0; i < 3; i ++)
        free(file->addr[i]);
    for(int i = 0; i < 3; i ++)
        file->addr[i] = NULL;
    //释放文件名
    if(file->filename != NULL)
    {
        free(file->filename);
		file->filename = NULL;
    }
    //释放文件内容
    if(file->content != NULL)
    {
        free(file->content);
		file->content = NULL;
    }
    //释放file指针
    free(file);
	printf("成功关闭!\n");
	return 0;
}

5 实验结果

菜单

文件的一系列操作

6 实验分析

    利用数组ldisk[C][H][B]构建磁盘模型,其中CHB分别表示柱面号、磁头号和扇区号。
当每个扇区大小为512B,且CHB分别为2、80和18时,一共占用空间大小为:

2*18*80*512B = 1474560B = 1440KB = 1.44MB 大小的空间

    系统的框架可以分为两部分,一部分是文件系统,另一部分是I/O系统。系统通过外壳程序与系统用户进行交互,接受用户命令或者反馈操作的结果,通过相应的命令对文件系统进行操作。文件系统再进而通过I/O系统对模拟磁盘进行读写操作。

 

GitHub链接:https://github.com/Tergerly/16281028/tree/master/实验五

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统实验中的proc文件系统是一种特殊的文件系统,主要用于提供操作系统内核信息的访问和管理。在实现proc文件系统时,需要完成以下几个主要步骤。 首先,需要定义一个proc文件结构体,用于描述proc文件的属性和操作。这个结构体通常包含文件名、文件大小、文件访问权限等信息,以便操作系统能够对其进行正确的处理。 接下来,需要实现创建proc文件的函数。这个函数负责在内核中创建一个proc文件,并将文件结构体与之关联。在创建过程中,需要为proc文件分配一个唯一的文件名,并指定相应的访问权限。 然后,需要实现读取proc文件内容的函数。这个函数会在用户空间打开proc文件时被调用,并将proc文件的内容返回给用户。根据不同的需求,可以通过读取内核变量或调用相关系统调用来获取文件内容。 此外,还需要实现写入proc文件内容的函数。这个函数会在用户空间对proc文件进行写入时被调用,并将用户输入的内容写入到相应的内核变量或系统调用中。 最后,还需要实现删除proc文件的函数。这个函数会在用户空间关闭proc文件操作系统关闭时被调用,负责释放proc文件的相关资源。 总之,实现proc文件系统需要定义文件结构体、创建、读取、写入和删除文件的函数。通过这些功能,用户可以在用户空间访问和管理内核的信息,提供了一个方便的方式来查看和调试操作系统内部状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值