第9章 Ext文件系统族 (3)

目录

9.2 Ext2文件系统

9.2.3 创建文件系统

9.2.4 文件系统操作

9.3 Ext3文件系统

9.3.1 概念

9.3.2 数据结构

9.4 小结


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

9.2 Ext2文件系统

9.2.3 创建文件系统

如何创建文件系统?

        mkfs 命令。

创建 Ext2 文件系统时,分配子目录" lost+found ",用于容纳介质上的坏块。

        若没有坏块,lost+found 目录为空。

创建步骤:

        1. dd if=/dev/zero of=img.1440 bs=1k count=1440

                //创建一个大小为1.4M,内容为0的文件。

        2. mkfs img.1440

                //在该文件上创建文件系统。

                //命令执行后,该文件包含超级块,GDT, inode等信息。

        3. mount -t ext2 -o img.1440 /mnt

                //挂载

9.2.4 文件系统操作

操作文件的内容:

        struct    file_operations

操作文件的对象本身:

        struct   inode_operations

操作文件的缓存:

        struct   address_space_operations

对应 Ext2 文件系统定义为:

struct   file_operations    ext2_file_operations   =   {

        .llseek                =       generic_file_llseek,

        .read                  =       do_sync_read,

        .write                  =       do_sync_write,

        .unlocked_ioctl   =       ext2_ioctl,

        .mmap                =       generic_file_mmap,

        .open                  =       dquot_file_open,

        .release              =       ext2_release_file,

        .fsync                  =       ext2_fsync,

};

generic开头的函数:表示为VFS通用函数。

//普通文件的操作

struct   inode_operations    ext2_file_inode_operations    =    {   

        .setattr      =    ext2_setattr,

        .get_acl    =     ext2_get_acl,

        .fiemap     =     ext2_fiemap,

};

//目录文件的操作

struct    inode_operations    dext2_dir_inode_operations    =    {

        .create     =     ext2_create,

        .lookup    =    ext2_lookup,

        .link          =    ext2_link,

        .unlink      =    ext2_unlink,

        .symlink    =    ext2_symlink,

        .mkdir       =    ext2_mkdir,

        .rmdir        =    ext2_rmdir,

        .rename    =     ext2_rename,

        .setattr      =     ext2_setattr,

};

//操作文件在内存中缓存

struct    address_space_operations    ext2_aops    =   {

        .readpage        =      ext2_readpage,

        .readpages      =      ext2_readpages,

        .writepage        =      ext2_writepage,

        .writepages      =      ext2_writepages,

        .migratepage    =      buffer_migrate_page,

};

struct     super_operations     ext2_sops    =    {

        .alloc_inode       =      ext2_alloc_inode,

        .destroy_inode   =     ext2_destroy_inode,

        .write_inode       =      ext2_write_inode,

        .put_super         =       ext2_put_super,

        .sync_fs             =      ext2_sync_fs,

        .remount_fs       =      ext2_remount,

};

1. 装载卸载

struct    file_system_type    ext2_fs_type    =    {

        .name      =     "ext2",

        .mount     =     ext2_mount,

        .kill_sb     =     kill_block_super,

};

ext2_mount函数作用:

        读取super block,已取代老版本.get_sb = ext2_get_sb。

struct   dentry    *ext2_mount(struct   file_system_type    *fs_type,   int   flags,   char  *dev_name,  void  *data)

{

        return    mount_bdev(fs_type,    flags,   dev_name,   data,    ext2_fill_super);

}

ext2_fill_super:

        作用:

                从磁盘读取信息,填充到超级块对象。

        步骤:

                检查magic。

                解析装载选项。

                检查特性。如读写模式,兼容特性,不兼容特性。

        设置块长度。

        从磁盘读取,并填充struct   super_block。

        读取组描述符。

        计算空闲 inode、块、目录数目。

        最后回写super到磁盘。

struct    ext2_sb_info:

        在内存保存文件系统超级块信息。

2. 读取并产生数据块和间接块

文件系统目的:

        关联一个文件和存储介质上对应块。

查找数据块

ext2_get_block() 函数作用:

        1. 分配空闲的磁盘中数据块。

        2. 查找文件数据存储在磁盘中的块位置。

请求新块

ext2_get_block() 函数:

        也可用于请求新块。

场景:写入数据,扩大文件时。

向文件添加新块,分为4个任务:

        1. 将新块关联到文件,判断是否需要间接块,几次间接。

        2. 在存储介质上查找并分配空闲块。

        3. 将新块添加到文件块列表中。

        4. 预留多余块。

块分配

ext2_alloc_branch函数:

        调用ext2_alloc_blocks完成。

预分配

ext2_try_to_allocate_with_rsv

3. 创建和删除inode

创建目录流程

sys_mkdir

        -> vfs_mkdir

                -> dir->i_op->mkdir(dir, dentry, mode);

                        //即 ext2_mkdir

int    ext2_mkdir(struct   inode    *dir,    struct   dentry    *dentry,    umode_t   mode)

{

        inode    =   ext2_new_inode(dir,   S_IFDIR | mode,   &dentry->d_name);

        inode->i_op   =   &ext2_dir_inode_operations;

        inode->i_fop   =   &ext2_dir_operations;

        inode->i_mapping->a_ops   =   &ext2_aops;

        ext2_make_empty(inode,   dir);

        ext2_add_link(dentry,   inode);

}

创建文件流程

sys_open系统调用:

        -> vfs_create

                -> dir->i_op->create(dir, dentry, mode, want_excl);

                        //即 ext2_create

int   ext2_create (struct  inode   *dir,   struct  dentry    *dentry,   umode_t    mode,   bool   excl)

{

        inode     =     ext2_new_inode(dir,     mode,    &dentry->d_name);

        inode->i_op   =   &ext2_file_inode_operations;

        inode->i_fop   =   &ext2_file_operations;

        inode->i_mapping->a_ops   =   &ext2_aops;

        mark_inode_dirty(inode);

        ext2_add_nondir(dentry,   inode);

}

ext2_new_inode:在硬盘中分配新的inode。

ext2_add_link:将新 inode 添加到父目录 inode 中。

4. 注册inode

inode分配策略:

        目录inode的经典分配(Linux 2.4之前)

        目录inode的Orlov分配。

        普通文件的inode分配。

5. 删除inode

分目录和文件的inode删除。

删除目录:

        最终调用 ext2_rmdir() 函数。

ext2_rmdir 包含两个操作:

        1. 从父目录inode数据块中删除对应目录项。

        2. 释放硬盘中数据块。

                包括:inode 和保存子目录项的数据块。

6. 删除数据块

可以删除数据块,需满足两个条件:

        1. 硬链接计数器为0(即未引用数据)

        2. inode的使用计数 i_count =0。

7. 地址空间操作

即读写文件在内存的缓存。

address_space:

        ext2_readpage

        ext2_writepage

9.3 Ext3文件系统

Ext3:即 Ext 文件系统的第三次拓展。

新增了日志(journal)特性。

作用:

        记录文件系统的操作。以便于崩溃后,使用fsck修复。

9.3.1 概念

日志特性的原理:

        1. 记录所有对元数据的操作到日志。

        2. 操作成功后从日志删除。

        3. 若崩溃导致,执行失败。日志将有记录到操作。

        4. 方便后续恢复,保证一致性。

缺点:仍无法避免数据丢失。

因为日志特性的开销,Ext3性能比Ext2低。

访问Ext3的三种方式:

        1. 回写模式

                日志只记录 inode 的修改,不记录对数据操作。

                特点:性能高,安全性低。

        2. 顺序模式

                日志只记录 inode 的修改,批量记录数据操作。

                默认的模式。

        3. 日志模式

                inode和数据的操作都记录到日志。

                特点:性能低,安全性高。

日志可存在一个文件,或一个分区。

9.3.2 数据结构

当进程打开一个Ext3或Ext4文件时,内核会为该文件打开一个日志(journal)。

作用:

        用于记录该进程对文件操作。

struct    task_struct {

        void    *journal_info;

}

journal_info 表示:

该日志的信息,所在起始地址、大小、块号等。

9.4 小结

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山下小童

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值