news 2026/5/20 10:21:01

4.1 VFS 虚拟文件系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
4.1 VFS 虚拟文件系统

1. VFS 概述

VFS (Virtual File System) 是 Linux 内核的文件系统抽象层,它为用户空间提供统一的文件系统接口,同时支持多种不同的文件系统。

1.1 VFS 的作用

用户空间

open/read/write/close

VFS层
统一接口
文件系统无关

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){// 解析路径path=user_path(dir_name);// 解析文件系统类型fstype=get_fs_type(type);// 调用文件系统的 mount 方法mnt=fstype->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;// 获取文件名name=getname(filename);// 分配文件描述符fd=get_unused_fd_flags(flags);if(fd<0)returnfd;// 打开文件f=do_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;// 路径解析dentry=path_lookupat(dfd,pathname,LOOKUP_PARENT,&path);if(IS_ERR(dentry))returnERR_CAST(dentry);// 创建 file 结构filp=alloc_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){structfdf=fdget_pos(fd);ssize_tret=-EBADF;if(f.file){// 获取当前偏移loff_tpos=file_pos_read(f.file);// 调用 VFS 读取ret=vfs_read(f.file,buf,count,&pos);// 更新偏移if(ret>=0)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_mode&FMODE_READ))return-EBADF;// 检查偏移if(unlikely(!access_ok(buf,count)))return-EFAULT;// 调用文件操作if(file->f_op->read)ret=file->f_op->read(file,buf,count,pos);elseret=do_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){structfdf=fdget_pos(fd);ssize_tret=-EBADF;if(f.file){loff_tpos=file_pos_read(f.file);ret=vfs_write(f.file,buf,count,&pos);if(ret>=0)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_mode&FMODE_WRITE))return-EBADF;if(unlikely(!access_ok(buf,count)))return-EFAULT;if(file->f_op->write)ret=file->f_op->write(file,buf,count,pos);elseret=do_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=='/'){// 从根目录开始dentry=dget(current->fs->root.dentry);}elseif(dfd==AT_FDCWD){// 从当前目录开始dentry=dget(current->fs->pwd.dentry);}else{// 从指定目录开始dentry=get_fd(dfd);}// 逐级解析while(*name){// 跳过分隔符name=skip_name(name,&this);// 检查权限err=inode_permission(dentry->d_inode,MAY_EXEC);if(err)gotofail;// 查找子目录dentry=lookup_one_len(name,dentry,len);if(IS_ERR(dentry))gotofail;// 移动到下一级name+=len;}*path=dentry;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_inode=inode;// 哈希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;// 计算哈希hash=full_name_hash(parent,name->name,name->len);head=&dentry_hashtable[hash&D_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 文件系统的核心抽象:

  1. 统一接口- 为所有文件系统提供相同 API
  2. 核心数据结构- super_block, inode, dentry, file
  3. 路径解析- 高效的目录项缓存
  4. 文件操作- open, read, write, close 等

理解 VFS 是深入学习文件系统的基础。


下一节:通用块设备层

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 10:19:16

fSpy完全上手指南:从基础到实战的零门槛教程

fSpy完全上手指南&#xff1a;从基础到实战的零门槛教程 【免费下载链接】fSpy A cross platform app for quick and easy still image camera matching 项目地址: https://gitcode.com/gh_mirrors/fs/fSpy 当你需要将一张普通的2D照片转换为精确的3D场景时&#xff0c;…

作者头像 李华
网站建设 2026/4/2 0:57:30

嵌入式开发中数据结构的优化与应用实践

1. 数据结构在嵌入式开发中的核心价值作为一名在嵌入式领域摸爬滚打十年的老兵&#xff0c;我深刻体会到数据结构就像瑞士军刀里的各种工具——选对工具能让工作事半功倍。在资源受限的MCU环境中&#xff0c;一个精心选择的数据结构可能意味着程序能否流畅运行和内存是否会爆掉…

作者头像 李华
网站建设 2026/4/7 16:32:58

C语言太头疼?试试Hare,专治指针内存报错

想象这般场景&#xff0c;有个从事C语言编程十几年的程序员&#xff0c;半夜三点时&#xff0c;仍在瞅着屏幕上的内存报错&#xff0c;急得抓耳挠腮。指针存在越界情况&#xff0c;出现内存泄漏问题&#xff0c;还有悬空指针现象&#xff0c;这些词汇仿若噩梦一般&#xff0c;纠…

作者头像 李华
网站建设 2026/4/2 0:52:04

Awesome-Embedded资源库:嵌入式开发者的实用指南

1. 嵌入式开发者的宝藏&#xff1a;Awesome-Embedded资源库解析作为一名在嵌入式领域摸爬滚打多年的工程师&#xff0c;我深知这个行业的痛点——资料零散、质量参差不齐&#xff0c;每次开启新项目都要花费大量时间搜集参考资料。直到发现了Awesome-Embedded这个开源项目&…

作者头像 李华
网站建设 2026/4/5 13:52:51

ESP32 ILI9341高性能驱动:64字节DMA突发传输优化

1. 项目概述ILI9341_ESP32 是一款专为 ESP32 平台深度优化的 ILI9341 TFT LCD 显示驱动库。其核心设计目标并非简单实现显示功能&#xff0c;而是在硬件能力边界内榨取极致帧率与响应性能。该库直面 ESP32 的 SPI 总线特性——支持 64 字节一次性突发传输&#xff08;burst tra…

作者头像 李华