虚拟文件系统这一层提供的大多数是形如vfs_xxx的函数,他们最终调用的还是各个具体的文件系统注册给虚拟文件系统的struct inode_operations和struct file_operations等结构体中的一些操作函数。以fat文件系统为例,他注册的struct inode_operations和struct file_operations如下:
//fs/fat/namei_vfat.c
static const struct inode_operations vfat_dir_inode_operations = {
.create = vfat_create,
.lookup = vfat_lookup,
.unlink = vfat_unlink,
.mkdir = vfat_mkdir,
.rmdir = vfat_rmdir,
.rename = vfat_rename,
.setattr = fat_setattr,
.getattr = fat_getattr,
};
//fs/fat/file.c
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,
.mmap = generic_file_mmap,
.release = fat_file_release,
.unlocked_ioctl = fat_generic_ioctl,
.fsync = fat_file_fsync,
.splice_read = generic_file_splice_read,
};
//fs/open.c
SYSCALL_DEFINE3(open, const char __user *, filename, ...)
do_sys_open
do_filp_open //fs/namei.c
path_openat
do_last
lookup_open
vfs_create
finish_open
do_dentry_open
f->f_op = fops_get(inode->i_fop);
在open的时候会将inode中结构体struct file_operations i_fop保存的函数指针赋值给file中的结构体struct file_operations f_op,以后read,write等函数调用的都是这里的struct file_operations结构体中的回调函数。
//fs/read_write.c
SYSCALL_DEFINE3(write, ...
vfs_write
file->f_op->write (fat文件系统为do_sync_write)
do_sync_write
filp->f_op->aio_write (fat文件系统为generic_file_aio_write)
generic_file_aio_write //mm/filemap.c
__generic_file_aio_write
generic_file_buffered_write
generic_perform_write
a_ops->write_begin
iov_iter_copy_from_user_atomic
a_ops->write_end
首先,系统调用write会调用虚拟文件系统中的函数vfs_write,vfs_write最终会调用fat文件系统注册的struct file_operations函数中的f_op->aio_write函数,generic_file_aio_write是在mm/filemap.c文件中实现的函数,这个函数会将数据写到page cache中,等待回写线程来将page cache写到磁盘中。
//fs/namei.c
SYSCALL_DEFINE2(mkdir, ...
sys_mkdirat
SYSCALL_DEFINE3(mkdirat, ...
vfs_mkdir(struct inode *dir, struct dentry *dentry, ...)
dir->i_op->mkdir
mkdir系统调用与write系统调用不一样,他会调用inode中的struct inode_operations结构体中的函数,而write系统调用调用的是file中的struct file_operations结构体中的函数。