11 ext2文件系统IO流程:读写文件read/write

ext2使用page页面缓存来完成对文件的读写。这些页面的管理是通过inode的字段i_mapping来完成,也就是地址空间。所以在创建inode时,要指定i_mapping的操作表a_ops,帮助地址空间完成页面操作。

参考:014 Linux文件系统数据结构详解:地址空间struct address_space

地址空间操作表a_ops中,需要指定读page、写page等多种页面操作的函数指针,但是具体的块操作(读取、写入)、buffer操作、VM页面操作,其实文件系统不用太关注,因为Linux内核提供了大量公共函数(参考:buffer.c和mpage.c),文件系统可以直接调用完成读取和写入。但是,文件系统需要提供块的映射方法,帮助完成文件系统逻辑块号(就是在文件中的偏移量)到实际块设备块号映射,最后填充到buffer_head中。

// inode.c

const struct address_space_operations ext2_aops = {
	.set_page_dirty		= __set_page_dirty_buffers,
	.readpage		= ext2_readpage,
	.readahead		= ext2_readahead,
	.writepage		= ext2_writepage,
	.write_begin		= ext2_write_begin,
	.write_end		= ext2_write_end,
	.bmap			= ext2_bmap,
	.direct_IO		= ext2_direct_IO,
	.writepages		= ext2_writepages,
	.migratepage		= buffer_migrate_page,
	.is_partially_uptodate	= block_is_partially_uptodate,
	.error_remove_page	= generic_error_remove_page,
};
继续阅读“11 ext2文件系统IO流程:读写文件read/write”

014 Linux文件系统数据结构详解:地址空间struct address_space

什么是地址空间address_space?是Linux内核提供的一种数据结构,通过该数据结构可以管理离散到各设备上的数据映射到内存的page缓存页面。

听起来很晦涩,其实地址空间就是一个中间层,内核把周边离散的设备组织起来,然后映射到page缓存页面,内核子系统通过地址空间,就可以操作这些page缓存页面,进而达到操作周边设备的目的。

所以page就是内核管理的虚拟内存空间,它是真实物理设备的在内存上的映射,通过操作page页面,就可以完成对具体物理设备操作,这样做的好处是:

  • ① 屏蔽了多种设备的物理差异,避免内核子系统直接访问物理设备
  • ② 相比CPU操作外设的等待时间,内存操作更加高效,提升了整体性能
  • ③ 文件在设备上可能是不连续的,通过page页面屏蔽这个矛盾,通过连续的page呈现给程序

举例说明:一个文件的数据存储在块设备上,内核将块设备映射到缓存页面page,VFS通过地址空间就可以操作缓存页面page,完成文件的读取和写入。

地址空间和虚拟内存
地址空间和虚拟内存
继续阅读“014 Linux文件系统数据结构详解:地址空间struct address_space”

10 ext2文件系统IO流程:inode的创建、写入、读取、删除、释放子流程

在Linux文件系统中,inode就代表一个磁盘上的文件,所有磁盘文件的操作,最终都落到inode上去处理,inode的生命周期管理非常重要。但是inode的创建、写入、读取和删除,通常不是独立的流程,它是裹挟在其它的大IO流程中,比如创建文件。但是在其它流程中,inode的处理的介绍几乎是一笔带过,所以,有必要针对inode管理,总结一篇详实的材料。本文还是以ext2文件系统为例,来讲述inode生命周期的管理。

首先,你要知道inode管理的操作函数,都是在超级块结构体里声明,因为inode自己的操作表,都是和文件操作相关。好,我们一起来看一下:

// super.c

static const struct super_operations ext2_sops = {
    .alloc_inode    = ext2_alloc_inode,
    .free_inode     = ext2_free_in_core_inode,
    .write_inode    = ext2_write_inode,
    .evict_inode    = ext2_evict_inode,
    .put_super      = ext2_put_super,
    .sync_fs        = ext2_sync_fs,
    .freeze_fs      = ext2_freeze,
    .unfreeze_fs    = ext2_unfreeze,
    .statfs         = ext2_statfs,
    .remount_fs     = ext2_remount,
    .show_options   = ext2_show_options,
};
继续阅读“10 ext2文件系统IO流程:inode的创建、写入、读取、删除、释放子流程”

08 ext2文件系统IO流程:删除文件unlink

前面几篇博客讲了创建文件、创建目录、查找文件,接下来说一下ext2文件系统是如何删除文件,ext2文件系统删除文件,并没有在物理设备上擦除文件,只是做了一个unlink操作,所谓的逻辑删除。unlink的具体实现,就是解除目录项与inode关系,这样目录项就不会关联到inode,就无法查找到文件,达到了删除的目的。unlink的具体的流程如下:

  • ① 根据文件名和父目录信息,到磁盘上查找目录项(ext2_find_entry),记录对应的页面page和页地址page_addr
  • ② 解除目录项与inode连接,然后删除目录项(逻辑删除,其实是与前一个目录项合并)
  • ③ 修改inode->i_ctime,递减inode的硬链接数i->nlink,同时标记脏inode
ext2 unlink操作
ext2 unlink操作
继续阅读“08 ext2文件系统IO流程:删除文件unlink”

02 ext2如何构造超级块super_block

上一篇介绍了ext2注册文件系统注册的流程,其中提到在注册文件系统时,给VFS传递了file_system_type结构体,在这个结构体中,包含了挂载函数指针ext2_mount(),用于挂载的回调操作。

在ext2_mount()函数实现中,调用了VFS的mount_bdev()来挂载块设备,这个mount_bdev()函数最后一个参数,是一个函数指针,VFS使用此函数完成超级块的构造和填充,而超级块是文件系统核心数据结构,它的构造是构建文件系统主要流程,本文就重点梳理一下超级块的构造,以下是mount_bdev()函数原型:

dentry *mount_bdev(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data,
	int (*fill_super)(struct super_block *, void *, int));
继续阅读“02 ext2如何构造超级块super_block”

004 虚拟文件系统VFS与进程相关的数据结构

上一篇介绍了虚拟文件系统VFS的基本数据结构,包括:文件系统类型file_system_type、超级块super_block、索引节点inode、目录项dentry和文件对象file。本篇文章着重看一下与进程相关的数据结构,包括files_struct和fs_struct,两者通过task_struct(进程)结构体粘结起来,通过fs_struct可以获取文件系统、挂载点、根dentry等信息,通过files_struct可以打开的文件对象,进而获取目录项、索引节点,最后和物理文件建立联系。

继续阅读“004 虚拟文件系统VFS与进程相关的数据结构”

003 虚拟文件系统VFS基本数据结构

Linux支持多种文件系统,这些具体的文件系统并不是直接都挂载到系统中的,实际上是按需挂载的,这些文件系统只有挂载到系统中,VFS才能够真正管理起来,否则如果只是注册,不会产生任何文件系统实例。

文件系统挂载(安装)后,将会产生多个数据结构实例,挂载过程实际上就是构造这些数据结构实例的过程。Linux在文件系统的设计中,汲取了Unix的设计思想,抽象出四个基本数据结构:超级块(super_block),索引节点(inode),目录项(directory entry)和文件对象(file)

文件系统主要数据结构
文件系统主要数据结构
继续阅读“003 虚拟文件系统VFS基本数据结构”

002 Linux内核中虚拟文件系统VFS组织方式和文件系统注册

Linux支持多种文件系统,据维基百科统计多达上百种,它是如何进行组织和管理这些文件系统?答案就是VFS。Linux内核使用VFS框架,来组织和管理多个文件系统,VFS叫虚拟文件系统,也叫(Virtual Filesystem Switch)。VFS是内核中的软件层,为用户空间程序提供文件系统接口,同时在内核中提供了一个抽象,允许不同的文件系统可以共存。

虚拟文件系统
虚拟文件系统
继续阅读“002 Linux内核中虚拟文件系统VFS组织方式和文件系统注册”