4.1 VFS 虚拟文件系统
1. VFS 概述VFS (Virtual File System) 是 Linux 内核的文件系统抽象层它为用户空间提供统一的文件系统接口同时支持多种不同的文件系统。1.1 VFS 的作用用户空间open/read/write/closeVFS层统一接口文件系统无关ext4本地磁盘NFS网络文件系统磁盘驱动网络驱动2. 核心数据结构2.1 超级块 (super_block)超级块存储文件系统的元数据// include/linux/fs.hstructsuper_block{// 设备信息dev_ts_dev;// 设备号unsignedlongs_blocksize;// 块大小unsignedchars_blocksize_bits;// 块大小位数// 文件系统类型structfile_system_type*s_type;// 超级块操作structsuper_operations*s_op;// 根目录structdentry*s_root;// 挂载选项char*s_options;// 标志unsignedlongs_flags;// 锁structrw_semaphores_umount;// 引用计数atomic_ts_active;// 私有数据void*s_fs_info;// 链表structlist_heads_list;};2.2 索引节点 (inode)inode 存储文件的元数据// include/linux/fs.hstructinode{// 索引号unsignedlongi_ino;// 设备号dev_ti_rdev;// 文件类型和权限umode_ti_mode;// 链接数unsignedinti_nlink;// 用户/组 IDuid_ti_uid;gid_ti_gid;// 文件大小loff_ti_size;// 时间戳structtimespec64i_atime;// 访问时间structtimespec64i_mtime;// 修改时间structtimespec64i_ctime;// 创建时间// 块计数unsignedinti_blocks;// 所属超级块structsuper_block*i_sb;// inode 操作structinode_operations*i_op;// 文件操作structfile_operations*i_fop;// 地址空间 (页缓存)structaddress_space*i_mapping;// 私有数据void*i_private;// 链表structlist_headi_sb_list;structlist_headi_dentry;// 引用计数atomic_ti_count;};2.3 目录项 (dentry)dentry 用于路径解析和目录缓存// include/linux/dcache.hstructdentry{// 目录项状态unsignedintd_flags;// 哈希值unsignedintd_hash;// 父目录structdentry*d_parent;// 文件名structqstrd_name;// inodestructinode*d_inode;// 别名链表structlist_headd_alias;// 子目录链表structlist_headd_child;// 父目录链表structlist_headd_subdirs;// 操作structdentry_operations*d_op;// 超级块structsuper_block*d_sb;// 私有数据void*d_fsdata;// 引用计数atomic_td_count;};2.4 文件描述符 (file)file 是用户空间文件描述符的内核表示// include/linux/fs.hstructfile{// 路径structpathf_path;// 文件操作structfile_operations*f_op;// 锁spinlock_tf_lock;structmutexf_pos_lock;// 文件偏移loff_tf_pos;// 标志unsignedintf_flags;// 模式fmode_tf_mode;// 引用计数atomic_tf_count;// 私有数据void*private_data;// 地址空间structaddress_space*f_mapping;};3. 文件系统注册与挂载3.1 注册文件系统// fs/super.c// 文件系统类型structfile_system_type{constchar*name;// 文件系统名称intfs_flags;// 标志structdentry*(*mount)(structfile_system_type*,int,constchar*,void*);void(*kill_sb)(structsuper_block*);structmodule*owner;structlist_headfs_supers;// 私有数据void*fs_info;};// 注册文件系统intregister_filesystem(structfile_system_type*fs){// 添加到文件系统链表list_add(fs-fs_supers,file_systems);return0;}3.2 挂载文件系统// fs/namespace.c// mount 系统调用SYSCALL_DEFINE5(mount,constchar__user*,dev_name,constchar__user*,dir_name,constchar__user*,type,unsignedlong,flags,constvoid__user*,data){// 解析路径pathuser_path(dir_name);// 解析文件系统类型fstypeget_fs_type(type);// 调用文件系统的 mount 方法mntfstype-mount(fstype,flags,dev_name,data);// 将挂载添加到命名空间mntput(mnt);}4. 文件操作4.1 打开文件// fs/open.c// open 系统调用SYSCALL_DEFINE3(open,constchar__user*,filename,int,flags,umode_t,mode){returndo_sys_open(AT_FDCWD,filename,flags,mode);}longdo_sys_open(intdfd,constchar__user*filename,intflags,umode_tmode){structfile*f;structfilename*name;intfd;// 获取文件名namegetname(filename);// 分配文件描述符fdget_unused_fd_flags(flags);if(fd0)returnfd;// 打开文件fdo_filp_open(dfd,name,op);if(IS_ERR(f)){put_unused_fd(fd);returnPTR_ERR(f);}// 关联到文件描述符表fdinstall(fd,f);returnfd;}// 实际打开文件structfile*do_filp_open(intdfd,structfilename*pathname,conststructopen_flags*op){structdentry*dentry;structfile*filp;// 路径解析dentrypath_lookupat(dfd,pathname,LOOKUP_PARENT,path);if(IS_ERR(dentry))returnERR_CAST(dentry);// 创建 file 结构filpalloc_file(path,flags,open_file_operations);returnfilp;}4.2 读取文件// fs/read_write.c// read 系统调用SYSCALL_DEFINE3(read,int,fd,char__user*,buf,size_t,count){structfdffdget_pos(fd);ssize_tret-EBADF;if(f.file){// 获取当前偏移loff_tposfile_pos_read(f.file);// 调用 VFS 读取retvfs_read(f.file,buf,count,pos);// 更新偏移if(ret0)file_pos_write(f.file,pos);fdput_pos(f);}returnret;}// VFS 读取ssize_tvfs_read(structfile*file,char__user*buf,size_tcount,loff_t*pos){ssize_tret;// 检查权限if(!(file-f_modeFMODE_READ))return-EBADF;// 检查偏移if(unlikely(!access_ok(buf,count)))return-EFAULT;// 调用文件操作if(file-f_op-read)retfile-f_op-read(file,buf,count,pos);elseretdo_sync_read(file,buf,count,pos);returnret;}4.3 写入文件// fs/read_write.c// write 系统调用SYSCALL_DEFINE3(write,int,fd,constchar__user*,buf,size_t,count){structfdffdget_pos(fd);ssize_tret-EBADF;if(f.file){loff_tposfile_pos_read(f.file);retvfs_write(f.file,buf,count,pos);if(ret0)file_pos_write(f.file,pos);fdput_pos(f);}returnret;}// VFS 写入ssize_tvfs_write(structfile*file,constchar__user*buf,size_tcount,loff_t*pos){ssize_tret;if(!(file-f_modeFMODE_WRITE))return-EBADF;if(unlikely(!access_ok(buf,count)))return-EFAULT;if(file-f_op-write)retfile-f_op-write(file,buf,count,pos);elseretdo_sync_write(file,buf,count,pos);returnret;}5. 路径解析5.1 路径查找// fs/namei.c// 路径解析structdentry*path_lookupat(intdfd,constchar*name,unsignedintflags,structpath*path){structdentry*dentry;constchar*s;// 处理绝对路径和相对路径if(*name/){// 从根目录开始dentrydget(current-fs-root.dentry);}elseif(dfdAT_FDCWD){// 从当前目录开始dentrydget(current-fs-pwd.dentry);}else{// 从指定目录开始dentryget_fd(dfd);}// 逐级解析while(*name){// 跳过分隔符nameskip_name(name,this);// 检查权限errinode_permission(dentry-d_inode,MAY_EXEC);if(err)gotofail;// 查找子目录dentrylookup_one_len(name,dentry,len);if(IS_ERR(dentry))gotofail;// 移动到下一级namelen;}*pathdentry;returnNULL;}6. 目录项缓存 (dentry cache)6.1 dentry 缓存Linux 使用 dentry 缓存加速路径解析// fs/dcache.c// 哈希表staticstructhlist_bl_head*dentry_hashtable;staticLIST_HEAD(dentry_unused);// 添加到缓存voidd_add(structdentry*entry,structinode*inode){// 设置 inodeentry-d_inodeinode;// 哈希d_hash(entry);// 添加到哈希表hlist_bl_add_head(entry-d_hash,dentry_hashtable[hash]);// 添加到 LRU 链表list_add(entry-d_lru,dentry_unused);// 增加引用计数atomic_inc(inode-i_count);}// 查找structdentry*d_lookup(structdentry*parent,structqstr*name){structhlist_bl_head*head;structdentry*dentry;// 计算哈希hashfull_name_hash(parent,name-name,name-len);headdentry_hashtable[hashD_HASHMASK];// 遍历链表hlist_bl_for_each_entry(dentry,head,d_hash){if(dentry-d_parent!parent)continue;if(dentry-d_name.hash!hash)continue;if(!dentry_cmp(dentry,name))returndentry;}returnNULL;}7. 总结VFS 是 Linux 文件系统的核心抽象统一接口- 为所有文件系统提供相同 API核心数据结构- super_block, inode, dentry, file路径解析- 高效的目录项缓存文件操作- open, read, write, close 等理解 VFS 是深入学习文件系统的基础。下一节通用块设备层