gcccode@
1. 引入文件系统概念
2. Linux 内核框架中的文件系统
3. 虚拟文件系统 VFS
5. Linux 文件系统之VFS基本管理对象简介
4. Linux 文件系统之分层思想
6. Linux文件系统之加载根文件系统
7. Linux 文件系统基本操作之挂载、打开及读写
内容概要
gcccode@
Linux 内核框架中的文件系统
第1步,格式化硬盘
第2步,文件创建、移动、删除文
件
系
统
的
作
用
gcccode@
应用程序
C库
核心内核
设备驱
动程序
硬件
内核空间
用户空间
系统调
用
网络 设备驱动程
序
VFS 文件系统
内存管理 进程管理
特定于体系机构的代码
* Linux 内核框架中的文件系统
引入文件系统概念
文件系统
页高速缓存 块设备IO
虚拟文件系统 VFS
VFS(virtual filesystem)支持的文件系统类型主要有三种:
1. 基于磁盘的文件系统,ext2,fat,ntfs
2. 网络文件系统,NFS
3. 特殊文件系统,procfs
接下来的PPT篇章均以第1种文件系统展开:
gcccode@
引导块
超级块
i节点位图 逻辑块位图 数据块
………………………………………………………
ext2分区 fat分区
引导块 数据组织管理元数据 实际数据存储单元 数据组织管理元数据 实际数据存储单元
ext2分区 fat分区
块设备IO层
页高速缓存层
文件系统数据组织层
文件系统接口管理层
Linux 文件系统之分层思想
块设备IO层:负责管理底层存储介质的数据存取;当接收上层并发的请求,还需负责处理协调请求的工作
页高速缓存层:为块设备IO层提供数据托管,利用“预读”和“延迟写”机制,提升I/O吞吐量
文件系统数据组织层:将存储介质晦涩的存储单元组织成用户容易理解并操作的对象,如文件;随着组织方式
的不同,也就出现了多种文件系统格式,如FAT、NTFS、EXT2、yaffs
文件系统接口管理层:VFS(virtual filesystem)提供统一接口,对上层用户来说,操作的是一文件,并不关心文件
在fat分区中还是ntfs分区;支持不同格式的文件系统间的操作
gcccode@
Linux 文件系统之VFS基本管理对象简介
超级块对象sb
s_list
s_dev
s_blocksize
s_dirt
s_type
……..
s_op
s_flags
s_root
……..
索引节点对象inode
………..
i_ino
i_dev
i_mode
i_uid,i_gid
i_rdev
i_atime,i_mtime,i_ctime
i_blksize,i_blocks
i_dentry
…………
文件对象file
f_next,f_pprev
f_dentry
f_op
f_mode
………..
f_pos
f_flags
f_owner,f_uid,f_gid
…………
目录项对象dentry
d_inode
d_parent
d_mounts
d_covers
………
d_name
d_op
d_sb
………
filesystem_type对象
name
fs_flag
read_super
next
vfsmount对象
mnt_dev
mnt_devname
mnt_dirname
mnt_flags
mnt_sb
mnt_dquoz
mnt_next
VFS基本管理对象
gcccode@
上图为Linux SDK平台启动完成后的终端界面;那么,在
此之前内核为它做哪些准备?
——加载根文件系统
Linux文件系统之加载根文件系统
gcccode@
Linux文件系统之加载根文件系统
对文件管理表file_table[]和超级块管
理结构super_block[]进行初始化设置
在super_block[]中申请空闲项
super_block[x]并进行初始化
把超级块从闪存里读进缓冲区,
并载入到刚申请的super_block[x]
通过超级块提供的信息,将闪存
中的i节点位图和逻辑块位图加载
到缓冲区
在i节点管理结构inode_table[]中申
请空闲项inode_table[x]
从闪存中读取根目录i节点,并将
其加载到i节点管理inode_table[x]
中
对超级块中与i节点相关的信息进
行设置,之后对空闲逻辑块和空
闲i节点的数量进行统计,并显示
文件管理表file_table[] 超级块管理表super_block[]
a. 系统将文件管理表所有项的引用计数清零 b. 系统将超级块管理表清空
超级块管理表super_block[] 缓存区
引导块
超级块
i节点位图 逻辑块位图 数据块
超级块管理表super_block[] 缓存区
引导块
超级块
i节点位图 逻辑块位图 数据块
超级块管理表super_block[] 缓存区
引导块
超级块
i节点位图 逻辑块位图 数据块
闪盘
闪盘
闪盘
第1步
第2步
第3步
第4步
第5步
第6步
第7步
第1步
第2,3步
第步
第步
加载超级块
a.分析超级块得知,闪盘上
i节点位图所占逻辑块个数 b. 加载i节点位图
a.分析超级块得知,闪盘上
逻辑块位图所占逻辑块个数 b. 加载逻辑块位图
gcccode@
Linux文件系统之加载根文件系统
对文件管理表file_table[]和超级块管
理结构super_block[]进行初始化设置
在super_block[]中申请空闲项
super_block[x]并进行初始化
把超级块从闪存里读进缓冲区,
并载入到刚申请的super_block[x]
通过超级块提供的信息,将闪存
中的i节点位图和逻辑块位图加载
到缓冲区
在i节点管理结构inode_table[]中申
请空闲项inode_table[x]
从闪存中读取根目录i节点,并将
其加载到i节点管理inode_table[x]
中
对超级块中与i节点相关的信息进
行设置,之后对空闲逻辑块和空
闲i节点的数量进行统计,并显示
超级块管理表super_block[] 缓存区
引导块
超级块
i节点位图 逻辑块位图 数据块
闪盘
第1步
第2步
第3步
第4步
第5步
第6步
第7步
第5,,6步
i节点管理表inode_table[]
加载根目录i节点到inode_table[x]
此时,根文件系统已加载完,系统初始化其他进程至shell,
便能以文件形式操作根文件系统中的数据,如下图:
gcccode@
Linux 文件系统基本操作之挂载、打开及读写
每次,将硬盘连接到平台,总要进行一次挂载动作,
如:
mount -t vfat /dev/sda1 /mnt/usb/sda1
为什么呢?操作的背后发生了什么?
gcccode@
filesystem_type对象
name:vfat
fs_flag
read_super
next
filesystem_type对象
name:ext2
fs_flag
read_super
next
filesystem_type对象
name:nfs
fs_flag
read_super
next
Linux 文件系统基本操作之挂载、打开及读写
内核初始化期间,调用filesystem_register()来注册内核编译时指定的文件系统
mount -t vfat /dev/sda1 /mnt/usb/sda1
2. 调用get_fs_type(),查看系统是否支持vfat文件系统,并设置sb->s_op为其read_super方法
3. 分析路径/dev/sda1,从而得到设备文件sda1的i节点和目录项对象,即可获得硬盘的超级块
4. 调用sb->s_op()加载超级块,并通过分析信息,加载i节点位图和逻辑块位图
1. 申请一空闲超级块项sb
5. 分析挂载点/mnt/usb/sda1,从而得到挂载点的i节点和目录项对象mnt_dentry
5. 将挂载点目录项对象mnt_dentry挂到sb->s_root下 超级块对象sb
s_type
……..
s_op
s_root
……..
目录项对象mnt_dentry
d_mounts
………
d_name:/mnt/usb/sda1
d_sb
………
用于确定文件系统类型vfat
用于从目标分区中加载超级块
确定该分区的挂载点
gcccode@
Linux 文件系统基本操作之挂载、打开及读写
目录项对象dentry
d_inode
d_parent
d_mounts
d_covers
………
d_name:/mnt/usb
/sda1/
d_op
d_sb
………
文件对象file
f_next,f_pprev
f_dentry
f_op
f_mode
………..
f_pos
f_flags
f_owner,f_uid,f_gid
…………
打开文件/mnt/usb/sda1/,流程如下:
int fd = open(“/mnt/usb/sda1/”, O_RDRW)
a. 通过路径名,在内核中找到其对应的目录项对象
const struct file_operations fat_file_operations =
{
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = fat_generic_ioctl,
.fsync = fat_file_fsync,
};
b. 申请一空闲file对象,
并将初始化其它成员,
如f_dentry,f_op,以确
定文件位置,及操作方式
c. 分配新的文件描述符fd与file关联,并返回给上层调用
用户空间
内核空间
超级块对象sb
s_dirt
s_type
……..
s_root
……..
注:找到超级块,即可知道该文件所属文件系统!
gcccode@
Linux 文件系统基本操作之挂载、打开及读写
文件对象file
f_next,f_pprev
f_dentry
f_op
f_mode
………..
f_pos
f_flags
f_owner,f_uid,f_gid
…………
读取文件/mnt/usb/sda1/,流程如下:
int count = read(fd, buf, size)
const struct file_operations
fat_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = fat_generic_ioctl,
.fsync = fat_file_fsync,
};
用户空间
内核空间
VFS
页高速缓存
a. 通过文件描述符fd找到
对应的文件对象file
b. 调用对应的read方法进行数据读取请求
c. 读取操作有两种方式:
i. DrectIO,直接让开页高数缓存,对块设备进行读取
ii. Readahead,带缓存预读,先将数据进行缓存,再传递
到上层调用者
d. 调用copy_to_user(),将目标数据送回上层调用
块设备IO
gcccode@
附:Windows vs. Linux之目录结构管理
1. Windows每个分区的路径是固定的
2. Linux 根文件系统是一颗虚拟的树,
不同的分区可以任意的挂载在树的节点上
gcccode@
总结
什么是文件系统? Linux文件系统是如何组织管理与实现的?
上层用户操作文件“背后的故
事”(文件系统的算法)
Linux文件系统管理基
本元素(数据机构)
实践
阅读内核代码:
1. 数据结构(事物间做综复杂的联系)
2. 算法(处理事务的逻辑关系)
系统优化无非就是:
时间与空间(CPU + 内存)
gcccode@