UNIX File System 实现

本文详细介绍了实现一个基于UNIX标准的文件系统的过程,包括文件分配方法(如连续分配、链表结构、I-Node),目录结构,空闲块管理,以及使用C语言实现的文件系统API接口。文中还探讨了缓存策略,并提到了实验中遇到的问题和未来改进的方向,如优化空闲块查找算法和限制缓存区大小。

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


title: UNIX File System 实现
tags:

  • Operating System
    categories:
  • Operating System
  • 随堂笔记
    abbrlink: 48303
    date: 2018-06-14 20:57:03

最后的大作业是实现一个文件系统,我以UNIX的文件系统为标准,实现了简单的文件系统和API接口。

本文的所有代码已经上传我的Github

要求

  • 设计一个文件系统,最多可以容纳5000个文件,设备容量为250MB,单个文件最大容量为50MB,提供目录树功能,文件名最长为50个字符,每块大小1KB
  • 本实验采用文件来模拟磁盘,采用dd命令创建文件,例如:dd if=/dev/zeroof=simulated_device bs=1024 count=250000将创建一个包含250000块文件名为simulated_device的文件。(这个文件可以满足测试程序中所有测试程序的空间需要)
  • 本实验已经给出测试文件,最大测试文件为50M。

思考

  • 实验要求很简单,就是实现一个普通的文件系统,而且实现方式不限,使用提供的write_block等接口来模拟低层的磁盘操作。
  • 设计一个文件系统,最主要的是思考如何布局。无论什么文件系统,都要包含目录树、文件信息等功能。
  • 文件的实现书上介绍了几种常见的方法:
    • 连续分配
      • 最简单的分配方案,将每个文件存放在连续的磁盘数据块中。
      • 易于实现,性能不错,但会造成大量外碎片(在多个小文件的时候经常发生)
    • 带有文件分配表的链表结构
      • 把每一个磁盘块中的链表指针抽取出来,单独组成一个表格,放在内存中。
      • 这样的坏处是整个文件分配表必须都放在内存,太占用空间。
    • I-Node
      • 大名鼎鼎的i-node登场啦。此i-node节点列出了文件的属性和各个数据库的磁盘地址,在给定一个i-node之后,就能找到该文件的所有信息。
      • 只有当一个文件被打开时,才需要把它的i节点装入内存。
      • i-node存储的磁盘地址不够时,我们还可以使用多级间接块(indirect block)来描述更多的磁盘地址。
  • 目录
    • 相对来说,目录的实现就简单多了。目录也可以理解为一种特殊的文件,UNIX中的目录非常简单,每一项(entry)只包含文件名i-node节点号两个信息。
  • 空闲块管理
    • 如何迅速知道磁盘中的空闲块以及剩余容量呢?
    • 一种方法是使用链表,但会占用大量空间。
    • 更常用的方法是使用位图(bitmap)来管理,已经分配的块用1表示,未分配的用0表示,每个块只占1个byte。
  • SuperBlock
    • 我们还需要一个SuperBlock作为文件系统的初始块。它应该包含文件系统初始化信息、位图地址、根目录地址等等,以便让系统将文件系统加载进内存。

实现

本项目使用了SuperBlockBitmap,以及i-node来实现文件系统。

  • Superblock
    • 是否初始化
    • 磁盘剩余空间(用于快速访问,了解该文件是否能放入磁盘)
    • bitmap信息(每个位图的使用情况)
    • 存储在第一块block中,当初始化时自动加载。
  • Bitmap
    • 按理来说,Bitmap中的每一个byte来代表一个块。但用byte操作不太直观,因此本项目使用short类型代替(会多浪费不少空间,但总占比空间依然不多)
    • 由于我们由250000个块,本项目设计每个Bitmap包含500个块的位图信息,其余地址用于存储起始磁盘块地址、剩余块多少。
    • 因此,我们需要500Bitmap,存储在第2~501个磁盘块中。
  • Root目录
    • Root目录也必须在文件系统初始化时加载和初始化,因此我们将它分配在502磁盘块上。
  • i-node
    • 在每个i-node中,我们设计了以下属性:
    • 文件大小
    • 创建、修改时间
    • 直接块(200个,可以存储200KB的信息)
    • 一级间接块(1个,可以存储256KB的信息–一条地址4bytes)
    • 二级间接块(1个,可以存储256*256KB的信息,完全足够我们用了)

总结下来,我们的文件系统大体框架如下图所示:

缓存

解决了文件系统的大体框架问题,接下来我们就要想缓存的问题了。因为我们不可能每次写都直接写到磁盘、每次读都直接从磁盘中读,这样一个block(1KB)一个block的读实在是太慢了。因此我想出了以下几个方法:

  • 每次write只写到缓存,只有当文件close的时候才真正写到内存。这种方法的好处是无论如何读写都很快,但当文件很大的时候非常占用内存。
  • 给内存分配一块专门用作文件读写的缓冲区,当文件大小小于缓冲区时,就直接将文件存储在缓存区中,当文件大于此大小,就将多余的部分存储在磁盘中。

理论上来说,第二种方案肯定是更好的,因为作为操作系统的一部分,肯定不希望占用过多的内存。但本项目为了简单,只采用了第一种方案。

代码逻辑

结构设计

因为文件系统涉及的结构层次较多,为了方便阅读代码,我整理了函数的逻辑如下:

52911994491

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值