Skip to content

Latest commit

 

History

History
192 lines (147 loc) · 6.87 KB

TODOs.org

File metadata and controls

192 lines (147 loc) · 6.87 KB

设计

shell 层


系统调用 文件操作 | 文件系统操作 | 目录操作 | 挂载文件系统(指定盘符和文件系统信息)


具体的某种文件系统的操作 文件操作 | 文件系统操作 | 目录操作


底层文件操作(该文件系统底层一切皆文件)


底层块文件操作(以块为单位的文件)


文件系统实现-和数据有关的数据结构 文件系统元信息 | inode 管理 | data-block 管理



模拟的 底层 IO 操作 io_read() 从模拟磁盘的扇区中读取内容 io_write() 向模拟磁盘的扇区中写入内容


模拟的 底层 IO 操作实际实现 标准库的文件操作函数

图形表示:

TODOs/design.png

类 unix 文件系统的设计

磁盘布局

Superblock | Inode table | Data blocks

superblock:超级块存放文件系统的全局控制信息。 Inode table: 一个大的 Inode 数组。每个块中存放一定的 Inode。 Data blocks: 存放文件内容的空间。

磁盘是以块 block 为单位管理的,一个 block 常用 1K,4K,64K。大小应该是扇区大小的整数倍。 block 从 0 开始编号,最大到 2^32 - 1,(uint32 的最大值)

假设 block 为 1K,可管理的最大磁盘容量达到 4T。

第一扇区存放 Spuerblock 的起始部分。包括最重要的信息:block 大小。也包括完整的 Spuerblock 所占用的 block 大小。 之后的几个扇区可能存放剩余的 Spuerblock 内容。 也许 superblock 的完整内容用一个扇区就能放入。但是即使这样,superblock 也会占用整数倍的 block 块。

Superblock

起始部分的 Superblock 包括:

struct superblock_t {
    uint16_t sectors_per_block; /* block 大小 */
    uint16_t size_per_sector; /* 扇区大小 */
    uint16_t superblock_used_block_count; /* spuerblock 总共占用的 block 块个数 */
}

剩余部分的 Superblock 包括:

struct superblock_t {
    uint64_t total_size; /* 文件系统总大小 */
    uint64_t used_size; /* 被使用的大小 */
    uint16_t root_dir; /* 指向根目录的 inode */
    uint32_t inode_table_block; /* inode table 起始的 block 号 */
    uint32_t data_block_free_stack; /* data block 的空闲管理相关 */
}

目前的设计搞简单点spuerblock 的东西不多假设它小于一个扇区的大小吧即使这样方便起见superblock 仍然占有第 0  block

关于 inode_table 的大小,data blocks 的起始 blocks 号能够根据已经有的信息计算出来。

inode

inode 储存的信息

Inode 的 mode 为 0 代表此 Inode 为空闲的。 此外,mode 可标示文件的类型:普通文件,目录,符号链接。 mode 为 0 表示此 inode 为空闲的。

编号为 0 的 inode 节点永远给根目录使用。

struct inode_t
{
  uint16_t mode; 
  uint16_t link_count;
  uint64_t size;
  uint32_t blocks[10];
  uint32_t single_indirect_block;
  uint32_t double_indirect_block;
  uint32_t triple_indirect_block;
  time_t accessed_time;
  time_t modified_time;
  time_t created_time; 
};

inode 数组

Inode table 区用连续的一定的 block 储存 inode 数组。 inode 不跨 block 储存,也就是一个 block 最多可储存整数个 inode。具体数量是:BLOCK_SIZE / sizeof(inode) 整个 Inode table 里面按顺序储存了一定的 inode。从 0 开始将其编号,到 2^16 -1(uint16 的最大值) 共有 2^16 个 inode。 因此用于储存 Inode table 的连续 block 块的个数为:2^16 / (BLOCK_SIZE / sizeof(inode)) (能整除加 0,不能整除加 1)

当 mode 为 0 时表示 inode 为空闲的。利用此来进行空闲 inode 的管理。

Data blocks

这里的 blocks 用于给文件的具体数据分配储存空间。

使用成组链接方式将空闲的 blocks 组成一个大栈套小栈的数据结构。。。

文件

这个文件概念和平常的文件概念不一样。

文件的 inode 中记录的文件的属性信息。 当文件大小不超过 10 * BLOCK_SIZE,使用 inode 节点的 blocks 数组直接指向储存数据的 data block。 放不下时,启用 single_indirect_block 的一级索引。 还放不下时,启用二级索引,之后三级索引。。。

目录

实际上,目录也是文件,只是在文件内容中放了目录表项。 目录表项占 16 字节,其中 14 字节为文件名,2 字节为其 inode 节点号。

普通文件

这个就是一般概念的文件。

符号链接

这个文件链接到另外一个文件上。被链接的文件路径放在文件内容中。

代码规范方面

所有命名一律使用下划线。

类型名称后一律加_t。

真正的全局变量(非设计意义上局限于某几个模块使用的),前加 g_。

看上一条。如果发现需要定义真正的全局变量,是否可以把它转换成函数调用的形式?

函数参数的顺序:IN 参数,EDIT 参数,OUT 参数。(附属参数例外)

工具之类的模块函数前加命名空间 ft_

系统调用层的模块函数前加命名空间 fufs_

其它的模块没有要求

字节敏感的地方, 不允许 使用 int 等类型,可以使用 stdint.h 中的类型。

工具

cmake http://hahack.com/codes/cmake/