一、引子

磁盘→盘片→磁道→扇区(每个 512 字节)

ext* 定义文件系统的格式

二、inode 与块的存储

1、块

2、不用给他分配一块连续的空间

我们可以分散成一个个小块进行存放

1、优点

2、存在的问题

3、如何解决

3、inode里面有哪些信息?

至于 inode 里面有哪些信息,其实我们在内核中就有定义。你可以看下面这个数据结构。

struct ext4_inode {
__le16 i_mode; /* File mode */
__le16 i_uid; /* Low 16 bits of Owner Uid */
__le32 i_size_lo; /* Size in bytes */
__le32 i_atime; /* Access time */
__le32 i_ctime; /* Inode Change time */
__le32 i_mtime; /* Modification time */
__le32 i_dtime; /* Deletion Time */
__le16 i_gid; /* Low 16 bits of Group Id */
__le16 i_links_count; /* Links count */
__le32 i_blocks_lo; /* Blocks count */
__le32 i_flags; /* File flags */
......
__le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
__le32 i_generation; /* File version (for NFS) */
__le32 i_file_acl_lo; /* File ACL */
__le32 i_size_high;
......
};

1、什么是inode?

2、基本信息

3、时间相关信息

4、i_blocks_lo

5、i_block

4、这些在 inode 里面,应该保存在 i_block 里面。

具体如何保存的呢?EXT4_N_BLOCKS 有如下的定义,

#define	EXT4_NDIR_BLOCKS		12
#define EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
#define EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
#define EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1)
#define EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1

1、如何保存?

2、文件比较大12块放不下?

3、文件再大些

4、文件更大一些

5、存在问题

三、Extents

ext4 引入 Extents 概念, 可以用于存放连续的数据块

优点:对于大文件的读写性能提高了,文件碎片也减少了

1、Extents是如何存储?

ext4_extent_header

struct ext4_extent_header {
__le16 eh_magic; /* probably will support different formats */
__le16 eh_entries; /* number of valid entries */
__le16 eh_max; /* capacity of store in entries */
__le16 eh_depth; /* has tree real underlying blocks? */
__le32 eh_generation; /* generation of the tree */
};

  

/*
* This is the extent on-disk structure.
* It's used at the bottom of the tree.
*/
struct ext4_extent {
__le32 ee_block; /* first logical block extent covers */
__le16 ee_len; /* number of blocks covered by extent */
__le16 ee_start_hi; /* high 16 bits of physical block */
__le32 ee_start_lo; /* low 32 bits of physical block */
};
/*
* This is index on-disk structure.
* It's used at all the levels except the bottom.
*/
struct ext4_extent_idx {
__le32 ei_block; /* index covers logical blocks from 'block' */
__le32 ei_leaf_lo; /* pointer to the physical block of the next *
* level. leaf or next index could be there */
__le16 ei_leaf_hi; /* high 16 bits of physical block */
__u16 ei_unused;
};

三、inode 位图和块位图

要保存数据是, 应放在哪? 全扫一遍效率低

 1、位图

2、块组

上海虹桥火车站的厕位智能引导系统,不知道你有没有见过?这个系统很厉害,我们要想知道哪个位置有没有被占用,不用挨个拉门,从这样一个电子版上就能看到了

do_sys_open

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE; return do_sys_open(AT_FDCWD, filename, flags, mode);
}

inode 操作的调用链

1、要打开一个文件,先要根据路径找到文件夹、如果发现文件夹下面没有这个文件,同时又设置了 O_CREAT
2、就说明我们要在这个文件夹下面创建一个文件,那我们就需要一个新inode

static int lookup_open(struct nameidata *nd, struct path *path,
struct file *file,
const struct open_flags *op,
bool got_write, int *opened)
{
......
if (!dentry->d_inode && (open_flag & O_CREAT)) {
......
error = dir_inode->i_op->create(dir_inode, dentry, mode,
open_flag & O_EXCL);
......
}
......
}

想要创建新的 inode,我们就要调用 dir_inode,
也就是文件夹的 inode 的 create 函数。它的具体定义是这样

const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create,
.lookup = ext4_lookup,
.link = ext4_link,
.unlink = ext4_unlink,
.symlink = ext4_symlink,
.mkdir = ext4_mkdir,
.rmdir = ext4_rmdir,
.mknod = ext4_mknod,
.tmpfile = ext4_tmpfile,
.rename = ext4_rename2,
.setattr = ext4_setattr,
.getattr = ext4_getattr,
.listxattr = ext4_listxattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
};

接下来的调用链是这样

struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
umode_t mode, const struct qstr *qstr,
__u32 goal, uid_t *owner, __u32 i_flags,
int handle_type, unsigned int line_no,
int nblocks)
{
......
inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
......
ino = ext4_find_next_zero_bit((unsigned long *)
inode_bitmap_bh->b_data,
EXT4_INODES_PER_GROUP(sb), ino);
......
}

四、文件系统的格式

一个位图只能表示 2^15 个数据块, 即 128MB

1、块组

超级块 ext4_super_block

一个 inode 位图 + 一个 block 位图, 称为块组, 用数据结构 ext4_group_desc 表示, 里面包含 inode 位图, block 位图和 inode 列表

这些块组描述符构成列表, 另外用超级块 ext4_super_block 描述整个文件系统; 第一个块组前 1k 用于启动引导

文件系统的组成

文件系统由引导块 + N 个块组组成; 每个块组由: 超级块 + 块组描述符表 + 块位图 + inode 位图 + inode 列表 + 数据块构成
超级块和块组描述符表都是全局信息; 默认超级块和块组描述符表再灭个租客都有备份; 若开启 sparse_super, 则只在固定块组中备份
采用 Meta Block Groups 特性, 避免块组表浪费空间, 或限制文件系统的大小

- 将块组分成多个组(元块组) 块组描述符表只保存当前元块组中块组的信息, 并在元块组内备份

struct ext4_super_block {
......
__le32 s_blocks_count_lo; /* Blocks count */
__le32 s_r_blocks_count_lo; /* Reserved blocks count */
__le32 s_free_blocks_count_lo; /* Free blocks count */
......
__le32 s_blocks_count_hi; /* Blocks count */
__le32 s_r_blocks_count_hi; /* Reserved blocks count */
__le32 s_free_blocks_count_hi; /* Free blocks count */
......
}

五、目录的存储格式

目录也是文件, 也有 inode, inode 指向一个块, 块中保存各个文件信息, ext4_dir_entry 包括文件名和 inode, 默认按列表存

struct ext4_dir_entry {
__le32 inode; /* Inode number */
__le16 rec_len; /* Directory entry length */
__le16 name_len; /* Name length */
char name[EXT4_NAME_LEN]; /* File name */
};
struct ext4_dir_entry_2 {
__le32 inode; /* Inode number */
__le16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT4_NAME_LEN]; /* File name */
};

第一项 "." 当前目录; 第二项 ".." 上一级目录

struct dx_root
{
struct fake_dirent dot;
char dot_name[4];
struct fake_dirent dotdot;
char dotdot_name[4];
struct dx_root_info
{
__le32 reserved_zero;
u8 hash_version;
u8 info_length; /* 8 */
u8 indirect_levels;
u8 unused_flags;
}
info;
struct dx_entry entries[0];
};

可添加索引, 加快文件查找

struct dx_entry
{
__le32 hash;
__le32 block;
};

需要改变目录块格式, 加入索引树: 用索引项 dx_entry 保存文件名哈希和块的映射, 若该块不是索引, 则里面保存 ext4_dir_enry 列表, 逐项查找

六、软链接和硬链接的存储格式

1、链接即文件的别名: ln -s 创建软链接; ln 创建硬链接
2、硬链接与原始文件共用一个 inode, 但不能跨文件系统
3、软链接是一个文件, 有自己的 inode, 该文件内容指向另一个文件, 可跨文件系统

七、总结时刻

这一节,我们描述了复杂的应哦按上的文件系统,但是对于咱们平时的应用来讲,用的最多的是两个概念,一个是inode、一个是数据块

为了表示图中上半部分的那个简单的树形结构,在文件系统上的布局就像图的下半部分一样,无论是文件夹还是文件,都有一个inode,inode里面的会指向数据块,对于文件夹的数据块,里面是一个表,是下一层的文件和inode的对应关系,文件的数据块里面存放的是真正的数据

趣谈Linux操作系统学习笔记:第二十八讲的更多相关文章

  1. 深挖计算机基础:趣谈Linux操作系统学习笔记

    参考极客时间专栏<趣谈Linux操作系统>学习笔记 核心原理篇:内存管理 趣谈Linux操作系统学习笔记:第二十讲 趣谈Linux操作系统学习笔记:第二十一讲 趣谈Linux操作系统学习笔 ...

  2. 趣谈Linux操作系统学习笔记:第二十讲

    一.引子 1.计算两方面的原因 2.内存管理机制 二.独享内存空间的原理 1.会议室和物理内存的关系 和会议室一样,内存都被分成一块块儿的,都编号了号,例如3F-10就是三楼十号会议室.内存页有这样一 ...

  3. 趣谈Linux操作系统学习笔记:第二十四讲

    一.小内存的分配基础 1.kmem_cache_alloc_node的作用 通过这段代码可以看出,它调用了kmem_cache_alloc_node函数,在task_struct的缓存区域task_s ...

  4. 趣谈Linux操作系统学习笔记:第二十五讲

    一.mmap原理 在虚拟内存空间那一节,我们知道,每一个进程都有一个列表vm_area_struct,指向虚拟地址空间的不同内存块,这个变量名字叫mmap struct mm_struct { str ...

  5. 趣谈Linux操作系统学习笔记:第二十六讲

    一.内核页表 和用户态页表不同,在系统初始化的时候,我们就要创建内核页表了 我们从内核页表的根swapper_pg_dir开始找线索,在linux-5.1.3/arch/x86/include/asm ...

  6. 趣谈Linux操作系统学习笔记:第二十九讲

    一.引子 在这之前,有一点你需要注意.解析系统调用是了解内核架构最有力力的一把钥匙,这里我们只要重点关注这几个最重要的系统调用就可以了 1.mount 系统调用用于挂载文件系统:2.open 系统调用 ...

  7. 趣谈Linux操作系统学习笔记:第二十七讲

    一.文件系统的功能规划 1.引子 咱们花了这么长的时间,规划了会议室管理系统,这样多个项目执行的时候,隔离性可以得到保证. 但是,会议室里面被回收,会议室里面的资料就丢失了.有一些资料我们希望项目结束 ...

  8. 趣谈Linux操作系统学习笔记:第二十一讲

    一.分段机制 1.分段机制的原理图 2.段选择子 3.段偏移量 例如,我们将上面的虚拟空间分成以下 4 个段,用 0-3 来编号.每个段在段表中有一个项,在物理空间中,段的排列如下图的右边所示. 4. ...

  9. 《趣谈 Linux 操作系统》学习笔记(一):为什么要学 Linux 及学习路径

    前言:学习的课程来自极客时间的专栏<趣谈 Linux 操作系统>,作者用形象化的比喻和丰富的图片让课程变得比较易懂,为了避免知识看过就忘,打算通过写学习笔记的形式记录自己的学习过程. Li ...

随机推荐

  1. 将Android封装库通过gradle部署到maven私服并依赖使用

    一.在需要发布的模块chrisbaselibrary下的build.gradle中添加以下部分 //maven插件 apply plugin: 'maven' //打包main目录下代码和资源的 ta ...

  2. TCP安全,SYN Flooding 和 nmap

    目录 SYN flooding nmap nmap idle SYN flooding 简介:向target持续发送SYN=1的TCP报文,使target因内存满而拒绝服务. 命令:netwox 76 ...

  3. MySQL Error Log 中IO写入瓶颈的警告分析

    周末在一台MySQL实例上频繁做大批量的写入测试,无意中发现MySQL的errorlog中频繁出现如下的Note:page_cleaner: 1000ms intended loop took *** ...

  4. 使用Apollo动态修改线上数据源

    前言 最近需要实现一个功能,动态刷新线上数据源环境,下面来使用Apollo配置中心和Spring提供的AbstractRoutingDataSource来实现. 具体实现 Apollo是携程开源的统一 ...

  5. JSON.parse和JSON.stringify方法

    1.JSON.parse(“要转换的数据”) 2.JSON.stringify(“要转化的数据”) 3.首先,两个方法的用法是有差别的: ①.JSON.stringify是从一个对象中解析出字符串 ② ...

  6. C++ std::list 基本用法

    #include <iostream> #include <string> #include <list> using namespace std; // http ...

  7. Bandizip解压压缩软件

    上次重装系统以后,特别注意安装软件,在这里提一些比较好的 解压软件:Bandizip 这个是一个免费轻量级的软件,压缩解压速度快,没什么广告,推荐大家在官方下载 Bandizip下载网址 点击下载安装 ...

  8. Windows10安装ubuntu18.04双系统教程

    写在前面:本教程为windows10安装ubuntu18.04(64位)双系统教程,是我多次安装双系统的经验总结,安装方法同样适用于ubuntu16.04(64位).为了直观和易于理解,我会尽量图文并 ...

  9. 集合系列 List(五):Stack

    Stack 是先进后出的栈结构,其并不直接实现具体的逻辑,而是通过继承 Vector 类,调用 Vector 类的方法实现. public class Stack<E> extends V ...

  10. Hive部分函数解析

    Hive部分函数解析 Hive里的exists ,in ,not exists ,not in 相关函数 表数据准备: 1.选择指定数据库 eg:  use bg_database1; 2. 创建表 ...