文件系统进阶
2018-05-17 18:02:49 37 举报
AI智能生成
克隆不点赞最没素质!!! 文件系统的基本数据结构和流程机制,xmind导入后,连线没了,悲催。
作者其他创作
大纲/内容
故事
时间线
一
有一个idea要存到优盘上
FAT32格式化优盘
每个bit都有了意义
layout
管理方法
把优盘插到linux系统上
linux系统抽象为块设备
块设备驱动创建块设备文件
/dev/block/sda
/dev/block/sda1
/dev/block/sda2
user
read
write
我们要告诉系统用什么文件系统的管理方法来处理优盘的字节
最终的呈现形式
目录+文件
user
fread
fwrite
块设备映射成目录
手动挂载
mount -t vfat /dev/block/sda1 /mnt/usb/sda1
内存中的分区管理数据结构
superblock
写文件操作三部曲
创建/打开文件
int fd = oepn("/mnt/usb/sda1/idea.txt",...);
路径上所有节点
inode缓存
struct inode+1
dentry缓存
struct dentry+1
还没有真正的文件产生
写入文件
write(fd,...);
被写入page
页缓存
page被刷新到磁盘
关闭文件
close(fd);
打开再欣赏一下
int fd = open("/mnt/usb/sda1.txt",...);
fstat(fd,...);
fd==>file==>path==>dentry==>inode==>stat
read(fd,...);
fd==>file==>address_space==>page==>memcpy
close(fd);
二
文件系统注册
vfat文件系统注册
module_init(init_vfat_fs)
static int __init init_vfat_fs(void)
{
return register_filesystem(&vfat_fs_type);
}
static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE,
.name = "vfat",
.mount = vfat_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
fat module注册
module_init(init_fat_fs)
init_fat_fs
fat_init_inodecache
文件系统全局注册链表
struct file_system_type *file_systems
struct file_system_type * next
数据结构
进程上下文
struct task_struct
实例变量
current
成员
struct files_struct *files
struct fs_struct *fs
struct fs_struct
成员
struct path root
struct path pwd
struct files_struct
成员
unsigned int next_fd
struct fdtable __rcu *fdt
struct fdtable fdtab
成员
struct file __rcu **fd;
struct file __rcu * fd_array[NR_OPEN_DEFAULT]
以int fd为下标
struct file
成员
struct inode *f_inode
struct file_operations *f_op
struct address_space *f_mapping
struct path f_path
struct path
struct dentry *dentry;
内存管理
struct address_space
成员
struct inode *host
当page是inode的page时,这个host就是inode,其他情况这里不讨论
struct address_space_operations *a_ops
struct radix_tree_root page_tree
一个文件的所有page
磁盘映射
struct inode
struct super_block *i_sb
struct address_space *i_mapping
struct inode_operations *i_op
struct buffer_head
在内存中对应块设备上的block
常见大小2 sector
1KiB
成员
struct buffer_head *b_this_page
每个page下的buffer构成单循环链表的next指针
struct page *b_page
struct page
成员
struct address_space *mapping
operation
struct file_operations
实例变量
fat_file_operations
.write_iter = generic_file_write_iter
成员
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)
struct address_space_operations
实例变量
fat_aops
成员
struct inode_operations
实例变量
vfat_dir_inode_operations
for目录inode
.lookup = vfat_lookup
struct inode dir_inode是目录inode
struct dentry dentry是要寻找的文件名
dir_inode->i_op->lookup(dir_inode, dentry,...);
若返回值!=NULL,则dentry对应的inode会和dentry连接起来
fat_file_inode_operations
for文件inode
.getattr = fat_getattr
成员
lookup
struct super_operations
实例变量
fat_sops
.write_inode = fat_write_inode
其它文件系统相关
struct file_system_type
实例变量
struct file_system_type *file_systems
成员
struct file_system_type * next
系统支持的文件系统的链表
struct dentry *(*mount) (struct file_system_type *, int, const char *, void *)
struct hlist_head fs_supers
已挂载分区的superblock链表
struct super_block
成员
struct file_system_type *s_type
struct super_operations *s_op
struct dentry
struct dentry_operations *d_op
struct inode *d_inode
调用流程
mount -t vfat /dev/block/sda1 /mnt/usb/sda1
vfat_mount
mount_bdev(..., vfat_fill_super)
vfat_fill_super
构造superblock
int fd = oepn("/mnt/usb/sda1/idea.txt",...);
SYSCALL_DEFINE3(open,...)
do_sys_open
int fd = get_unused_fd_flags(flags);
return __alloc_fd(current->files,...);
找到一个可能可用的int fd
struct file *f = do_filp_open(dfd, tmp, &op);
struct file *filp = path_openat(...);
在路径上建立inode和dentry
fd_install(fd, f);
fd_array[fd] = f
write(fd,...);
SYSCALL_DEFINE3(write,...)
vfs_write
__vfs_write
new_sync_write
fat_file_operations.write_iter
generic_file_write_iter
__generic_file_write_iter
generic_perform_write
fat_aops.write_begin
iov_iter_copy_from_user_atomic
写入page
fat_aops.write_end
...
mark_inode_dirty(inode);
...
__block_commit_write
将一个page的脏block标记为脏
初始化bh
struct buffer_head bh = head = page_buffers(page);
循环体
mark_buffer_dirty(bh);
bh = bh->b_this_page;
终止条件
while (bh != head)
balance_dirty_pages_ratelimited
每写入一个page,就会平衡脏页数,脏页太多就会写到块设备一些
balance_dirty_pages
writeback_in_progress(wb)
看看后台写回是否在进行
wb_start_background_writeback(wb)
唤醒后台写回进程
generic_write_sync
vfs_fsync_range
fat_file_operations.fsync
fat_file_fsync
generic_file_fsync
__generic_file_fsync
sync_mapping_buffers
fsync_buffers_list
write_dirty_buffer
submit_bh
submit_bh_wbc
submit_bio
generic_make_request
发送bio请求给block device,会写入块设备
fstat(fd,...);
SYSCALL_DEFINE2(fstat,...)
vfs_fstat
vfs_getattr
vfs_getattr_nosec(struct path *path, struct kstat *stat)
struct inode *inode = d_backing_inode(path->dentry);
return inode->i_op->getattr(path->mnt, path->dentry, stat);
fat_file_inode_operations.getattr
fat_getattr
generic_fillattr
read(fd,...);
SYSCALL_DEFINE3(read,...)
vfs_read
__vfs_read
new_sync_read
fat_file_operations.read_iter
generic_file_read_iter
do_generic_file_read
copy_page_to_iter
机制
文件系统缓存
在内存中建立这些对象时,
会在缓存中建立和释放
inode缓存
每个文件系统自己维护
FAT
init_fat_fs
fat_init_inodecache
fat_inode_cachep
kmem_cache_create("fat_inode_cache",
sizeof(struct msdos_inode_info),
0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD|SLAB_ACCOUNT),
init_once)
dentry缓存
dcache_init
dentry_cache
缓存
dentry_hashtable
哈希查找表
buffer缓存/块缓存
buffer_init
bh_cachep
kmem_cache_create("buffer_head",
sizeof(struct buffer_head), 0,
(SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
SLAB_MEM_SPREAD),
NULL)
写回
改动page、buffer、inode
mark dirty
inode
__mark_inode_dirty
inode_io_list_move_locked
wb_wakeup_delayed
buffer
mark_buffer_dirty
__mark_inode_dirty
__set_page_dirty
page
__set_page_dirty
执行写回
wb_workfn
注册
当插入优盘时,会启动backing device初始化
bdi_init
INIT_LIST_HEAD(&bdi->bdi_list);
backing device info链表
cgwb_bdi_init
wb_init
INIT_LIST_HEAD(&wb->work_list);
INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
注册写回work执行函数
流程
pages_written = wb_do_writeback(wb)
处理队列的work
wb_writeback
writeback_sb_inodes
struct writeback_control wbc = {
.sync_mode = work->sync_mode,
.tagged_writepages = work->tagged_writepages,
.for_kupdate = work->for_kupdate,
.for_background = work->for_background,
.for_sync = work->for_sync,
.range_cyclic = work->range_cyclic,
.range_start = 0,
.range_end = LLONG_MAX,
}
__writeback_single_inode
do_writepages
struct address_space_operations xxx_aops.writepage
fat_writepage
block_write_full_page
__block_write_full_page
submit_bh_wbc
submit_bio
generic_make_request
发送bio请求给block device,会写入块设备
write_inode
如果这个inode没有脏页,就更新inode到磁盘
struct super_operations xxx_sops.write_inode
write_inode
struct super_operations xxx_sops.write_inode
mod_delayed_work(bdi_wq, &wb->dwork, 0)
定时唤醒自己
0 条评论
下一页