pintos pro4 filesystem 设计报告
Project 4 FileSystem
作者:西安电子科技大学 王永刚  QQ:357543420
2014.2.7
      文件系统是操作系统的五大功能模块之一,主要实现操作系统对程序、数据、设备等的管理。
一、当前pintos文件系统的功能
当前pintos文件系统已经实现了基本的文件创建删除功能。文件是固定大小,连续存放的。
(1)文件在磁盘的存储方式:
    每个文件都有一个disk_inode存放在磁盘的一个扇区上,其结构如下:
struct inode_disk
{
    block_sector_t start; //文件数据每一个起始块
    off_t length;      //文件长度。
    unsigned magic;    //三月英文缩写
    uint32_t unused[125];
};
现在pintos文件是连续的,而且在创建时指定其大小后,再不能改变大小。由起始扇区和文件大小就能到所有文件数据。
目录也是一个文件,只是其内容中都存放如下结构:
struct dir_entry
{
    Block_sector_t inode_sector;  //文件inode_disk 所在扇区。
Char name[NAME_MAX+1];
Bool in_use;
};
(2)磁盘空闲空间管理方式。
空闲空间是用位图来表示的。其中位图也是一个文件,其disk inode存放在Sector 0.
位图文件大小显然与磁盘大小有关,用一个位表示一个扇区是否被分配,一个扇区512字节,一个扇区作为一个物理块,创建一个2M的磁盘,有1024*1024*2/512bit=4096bit= 4096/8=512Byte。
(3)文件系统初始化过程:
在init.c:main()函数中调用了filesys_init();
1. 在filesys_init()中,初始化了bitmap,而且对磁盘进行了格式化。其中格式化就是创建了两个文件,一个用来管理空闲块的位置图文件,一个是根目录文件。
赴怎么读隋炀帝的诗2.Filesys_init()中调用了free_map_init(),在free_map_init()中调用bitmap_create()创建了位图,大小依据磁盘大小。而且标记了0 1两个扇区为已经分配,作为free_map_file的disk_inode空间和根目录文件的disk_inode空间。此时free_map只是在内存中。
3.Filesys_init()中又调用了do_format()
在do_format()中:调用 了free_map_create(),创建了free_map_file,即一个文件,其disk_inode已经在上面分配了,再分配文件大小即可,这是由调用inode_create函数来实现的。创建这个文件时显然需要分配磁盘空闲块,就从在内存中的free_map位图中分配就可以。文件创建好了之后,打开文件,把内存中的位图free_map写到磁盘上,这是调用bitmap_write()实现的,本质还是用file_write()实现的。File_write()是通过inode_write_at()写磁盘的。
在do_format()中还创建根目录文件,ROOT_DIR_SECTOR已经标记了,分配文件所需要的空间就行了。
4. Filesys_init()调用了free_map_open()把free_map读入内存。其实就是打开上面创建的free_map文件,读数据入内存。直到系统关闭时才将free_map写回到磁盘上。
    首先在内存中建立了磁盘的位图,标记了根目录和free_map本身的disk_inode结构扇区。
  上面的内存free_map一建立就保证创建文件时可以分配磁盘空间了。而inode_create()中就需要调用free_map_allocate()来获取空闲物理块。如果不格式化,则以前必然格式化过,直接读入free_map就行。
(4)目录创建过程。
Pintos原来已经实现了创建目录的功能,但是只创建根目录,而且根目录只能包含16个文件,即16个dir_entry结构。
目录本质也是一个文件,根目录是特殊的文件,在filesys.h中有宏定义:
#define ROOT_DIR_SECTOR 1.
在ROOT_DIR_SECTOR中,也就是第1个扇区中存放了根目录的disk_inode.上面已经提到了,在格式化时创建了根目录。
(5)文件打开过程。
调用filesys_open().
每个打开的文件在内在都维护了一个唯一的数据结构inode(为了与disk_inode区别,这个叫memory inode).以下是memory inode结构:
Struct inode
{
        Struct list_elem elem;
        Block_sector_t sector;
Int open_cnt;
Bool removed;
Int deny_write_cnt;
Struct inode_disk data;
};
打开一个文件显然就是在内存中创建一个inode结构,其中struct inode_disk data保存了该文件对应的磁盘中的inode. 如果此文件已经打开了,则只需要增加open_cnt的值,不用再创建一个inode. 这些inode通过一个链表链结到一起的,在filesys_init()中初始化了这个链表。
具体过程:
            调用filesys_open(const char filename); 首先打开根目录,然后在根目录中依据filename查文件。如果到了,也就是到了此文件对应的struct dir_entry结构,里面记录了文件disk_inode, disk_inode中记录文件数据起始位置和文件大小,这就可以读写文件了。当然,还需要建立文件对应的memory inode.其中 data就是此文件的disk_inode.
通过filesys_open()只能得到文件的inode. 如果此文件是普通文件,则调用fileopen(inode)把inode包装成struct file结构;如果是目录就调用dir_open把inode包装成struct dir.
Struct file结构如下:
Struct file
{
        Struct inode  *inode;
        Off_t  pos;
    Bool deny_write;
};
(6)文件的创建过程.
创建一个文件要有文件名和文件大小,每一个文件在磁盘中都有一个struct disk_inode
结构,每个文件和目录都要在一个目录下,在目录文件中,struct dir_entry中记录了每个该目录下的文件的文件名,以及每个文件disk_inode所在扇区号。
具体是通过调用filesys_create(const char *name,off_t initial_size)实现的.
  首先调用struct dir *dir =dir_open_root()打开根目录。以下struct dir结构。
Struct dir
{
      Struct inode *inode;
  Off_t pos
}; 本质就是一个文件,读写目录与读写普通文件没有区别。
然后调用free_map_allocate分配一个扇区sector作为新文件的disk_inode.
再调用inode_create(sector,initial_size)分配文件所需要磁盘空间,分配的空间是连续的扇区。
最后创建一个struct dir_entry结构,把文件名和其sector填入其中,在目录中一个位置放
入就可以了。
(7)文件的读写。
调用filesys_open()打开文件,这就得到了struct file结构,如下:
些结构记录了当前文件指针位置pos。
File_read() file_write()分配是通过inode_read_at()和inode_write_at()实现的。
二、 对disk_inode的改进
当前pintos文件系统限制很大。文件需要连续存储,这会导致大量磁盘碎片。
文件大小固定,不能动态增长文件,只有一个目录。这里主要把连续存储方式改为了linux中三级索引结构,而且可以动态增长文件,可以创建子目录。
三级索引结构:
0
1
2
3
程序定时关闭器
4
5
6
7
8
9
10
11
sim卡注册失败是什么原因
12
13
14
0—11是直接块,存入文件
512
128
512
128
512
128
数据块扇区号。                                               
12是一级索引
13是二级索引
健康饮食手抄报内容
Data
……
512
128
512
128
14 是三级索引
data
512
128
如果一个物理块是512字节
每个物理块中用四字节
data
直接块:12*512=6K
一级索引:128*512=64K
二级索引:128*128*512=8M
三级索引:128*128*128*512=1GB
总大小1GB8M72K
通过修改struct disk_inode结构来实现三级索引结构。修改过的disk_inode
Struct inode_disk
{
    Off_t length;                  //文件长度
    Uint32_t blocks[BLOCK_NUM];  //三级索引区
    Unsigned isdir;                //此文件是不是目录
Unsigned magic;               
Uint32_t unused[110]; 
};
修改inode_create()
Inode_read_at()
Inode_write_at()
三个函数即可。
空闲磁盘块依然用位图管理。可以用free_map_allocate()获得一个空闲物理块。
用free_map_release()来释放物理块。只用写文件才有可能增长一个文件的大小。
读写文件一般是给出.
1.改变了disk_inode, 自然要从inode_create开始入手。代码见附录。
因为要区分目录和普通文件,所以对原来的inode_create进行了扩展,改为了bool  inode_create_ex (block_sector_t sector, off_t length,uint32_t isdir);增加了isdir参数。重新定义了一个函数:
bool inode_create(block_sector_t sector,off_t length)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。