📄 vfs+-+
字号:
any questions,send email to netxiong@eyou.com
相关文件
/fs/read_write.c
/drivers/block/ll_rw_blk.c
/fs/block_dev.c
*********************读写请求的顺序************************
当用户使用write进行系统调用的时候,文件句柄被传给了系统调用函数sys_write,
在这个系统调用函数内,将对句柄进行判断,分析出是哪一种设备,然后得到该设备的inode节点,
从这个节点中,得到相应的fops处理函数集,从而可以调用不同的设备处理函数。
***********************************************************
*****************文件系统的读写顺序*****************************
这时系统中最为复杂的一部分。
(1)首先,对于一个文件系统来说,它的结构如下,以ext2文件系统为例。
struct files_struct
count;
file_lock;
struct file ** fd;
struct file * fd_array[NR_OPEN_DEFAULT];
struct file
struct file_operations *f_op
struct dentry *f_dentry;//包含inode
(2)系统中有一个块设备的fops操作集
//这个操作集是对于一般的块设备而言的,
struct file_operations def_blk_fops = {
open: blkdev_open,
release: blkdev_close,
llseek: block_llseek,
read: block_read,
write: block_write,
fsync: block_fsync,
ioctl: blkdev_ioctl,
};
它的调用地方在/fs/devices.c中的init_special_inode函数中
(3)系统调用init_special_inode(struct inode *inode, umode_t mode, int rdev)来 对默认的各种设备的fops集进行设置,对mode进行检查,从而确定是char设备还是block设备等。如果是block设备,那么就将inode中的i_fops域设置成为&def_blk_fops
(4)在/fs/ext2/inode.c文件中,函数void ext2_read_inode (struct inode * inode)负责对这个文件系统的inode进行设置,首先对参数inode中的i_mode进行检查,如果是这个inode代表的是文件的话,那么inode->i_fop = &ext2_file_operations;他的操作集就是相应的ext2文件系统的操作集,如果是目录的话,那么inode->i_fop = &ext2_dir_operations;对应的就是ext2文件系统的目录操作集,如果都不是的话,就说明是其中的设备文件等其他种类的文件,就调用init_special_inode进行块设备的操作集的设置。
(5)在/fs/ext2/file.c中定义了对于普通ext2文件的操作集,
struct file_operations ext2_file_operations = {
read: generic_file_read,
write: generic_file_write,
}
(6)对于普通的文件系统中普通文件的读写,vfs提供了一系列的通用的读写函数,例如,写文件的操作generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos),这个函数中主要是对在inode中的i_mapping中的数据,也就是要写入的数据,调用mapping中的a_ops操作集中的commit_write来进行读写。
(7)在文件/fs/ext2/inode.c中,定义了struct address_space_operations ext2_aops 结构,也就是对内存中的数据进行读写的操作,应为,所有的文件的读写都是通过内存中的buffer来进行的,在这个操作集中定义了commit_write: generic_commit_write,也就是提交buffer写的函数。
(8)在文件/fs/buffer.c中,定义了函数 generic_commit_write(struct file *file, struct page *page,unsigned from, unsigned to),在函数内部,调用了一个新的函数__block_commit_write(inode,page,from,to),在这个函数体内,调用了 __mark_dirty(bh),将相应的bh定义为了脏数据,剩下的事情就是由守护进程bdflush完成了。
(9)在文件/fs/buffer.c中定义了守护进程int bdflush(void *sem),这个进程调用了函数flush_dirty_buffers(0);对需要进行刷新的buffer进行相应的写操作。
(10)在文件/fs/buffer.c中定义了刷新函数static int flush_dirty_buffers(int check_flushtime),这个函数扫描整个lru链表,检查那些应该被刷新到磁盘上的buffer,然后加锁,进行写操作如下
atomic_inc(&bh->b_count);
spin_unlock(&lru_list_lock);
ll_rw_block(WRITE, 1, &bh);
atomic_dec(&bh->b_count);
其中最为重要的就是这个ll_rw_block函数了,他就调用bh中相应的fops操作集对buffer进行相应的操作。
(11)剩下的工作就参看block设备的处理过程了
****************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -