【Note】《深入理解Linux内核》Chapter 16 :深入理解 Linux 文件访问机制
《深入理解Linux内核》Chapter 16 :深入理解 Linux 文件访问机制
关键词:VFS、文件描述符、struct file、struct inode、open、read、write、close、dentry、权限校验、file_operations、O_NOATIME、权限继承
一、概览:Linux 文件访问路径
在 Linux 中,几乎一切资源都可以通过“文件”的形式访问。文件访问不仅涵盖传统的磁盘文件,还包括设备、管道、socket、内存映射对象等。
1.1 文件访问操作的主要系统调用
int open(const char *pathname, int flags, mode_t mode);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
1.2 高层用户行为与内核调用链映射关系
open() ──> sys_open() ──> do_sys_open()
└─> do_filp_open()
└─> namei 解析
└─> permission 检查
└─> 创建 struct file / struct dentry / struct inode
整个文件访问路径经过 VFS(Virtual File System),它为所有具体文件系统(如 ext4、xfs)提供统一抽象接口。
二、文件访问核心数据结构
2.1 struct file
表示进程打开的一个“活跃”文件(open file instance):
struct file {
struct file_operations *f_op;
struct dentry *f_dentry;
struct vfsmount *f_vfsmnt;
loff_t f_pos; // 文件指针
unsigned int f_flags; // 打开标志 O_RDONLY 等
mode_t f_mode; // 访问权限
...
};
- 每次
open()都会生成一个新的struct file实例; - 多个进程可共享同一
inode,但file各自独立。
2.2 struct inode
表示文件的元信息(持久存在于文件系统中):
struct inode {
umode_t i_mode;
struct file_operations *i_fop;
unsigned long i_ino; // inode 编号
struct super_block *i_sb;
...
};
- 包含权限、类型、大小等元数据;
- 指向实际文件系统方法。
2.3 struct dentry
路径名与 inode 的绑定:
struct dentry {
struct inode *d_inode;
struct dentry *d_parent;
struct qstr d_name;
...
};
- 提供快速路径名缓存(dcache);
- 减少路径查找成本。
三、文件描述符(File Descriptor)管理
3.1 文件描述符本质
文件描述符是用户空间表示“打开文件”的整数编号,其实是进程文件描述表的下标。
struct files_struct {
struct file **fdt; // file descriptor table
};
每个进程拥有一份 files_struct,记录其打开的所有文件。
3.2 分配流程
get_unused_fd_flags():分配描述符;fd_install():将 struct file 与 fd 绑定;- 返回 fd 给用户空间。
3.3 close() 释放流程
sys_close(fd)→filp_close();- 文件引用计数减少;
- 若为0,则释放 file,关闭底层资源。
四、open 系统调用流程详解
4.1 系统调用入口
SYSCALL_DEFINE3(open, const char __user *, filename,
int, flags, umode_t, mode)
4.2 执行路径
sys_open()
└── do_sys_open()
└── get_unused_fd()
└── do_filp_open()
└── open_namei() // 路径解析
└── inode_permission()
└── alloc_file()
└── fd_install()
4.3 特殊标志处理
O_CREAT:若文件不存在则创建;O_TRUNC:打开时清空文件;O_APPEND:每次写入追加;O_DIRECTORY:仅允许打开目录;O_NOATIME:不更新访问时间。
五、路径名解析与权限校验
5.1 名称解析:namei 机制
do_filp_open() 调用 path_openat() 执行路径查找:
path_lookupat()
└── walk_component() // 按“/”逐级查找
└── dcache 查找 dentry
└── 最终找到目标 inode
5.2 权限检查:inode_permission()
根据 inode 上的权限位与当前进程身份(UID/GID)判断是否允许访问。
bool inode_permission(struct inode *inode, int mask);
六、read() / write() 调用路径与文件系统接口
6.1 read() 调用链
sys_read()
└── vfs_read()
└── file->f_op->read_iter()
└── generic_file_read_iter()
└── filemap_read() // 页缓存操作
- 页缓存命中则直接返回数据;
- 否则调用 readpage 从磁盘读取。
6.2 write() 调用链
sys_write()
└── vfs_write()
└── file->f_op->write_iter()
└── generic_file_write_iter()
└── filemap_write()
- 将用户数据拷贝到页缓存;
- 标记页面为脏(dirty);
- 后台回写到磁盘。
七、文件关闭流程 close()
7.1 close 调用链
sys_close()
└── filp_close()
└── fput()
└── file->f_op->release()
- 文件关闭后释放内核资源;
- 若是 socket、管道等可能触发数据发送/同步。
八、文件打开的共享与继承
8.1 多进程共享文件
- 父子进程通过 fork() 会共享打开的文件;
- 描述符表复制,但 struct file 不复制;
- 使用 dup() / dup2() 可在进程中手动复制描述符。
8.2 exec() 后文件处理
- 非
O_CLOEXEC文件描述符默认会保留; - 使用
fcntl(fd, F_SETFD, FD_CLOEXEC)设置关闭标志。
九、VFS 中的文件操作方法表(file_operations)
文件系统驱动实现 file_operations,VFS 会在 open() 时设置 file->f_op 指针:
struct file_operations {
ssize_t (*read) (...);
ssize_t (*write) (...);
int (*open) (...);
int (*release) (...);
int (*mmap) (...);
...
};
- VFS 提供统一接口;
- 文件系统提供底层实现;
- 用户空间无感知。
十、访问控制机制与扩展支持
10.1 标准 UNIX 权限模型
- 文件 inode 包含权限位(rwx);
- UID、GID 与进程身份匹配后生效。
10.2 Access Control List(ACL)
支持更细粒度的权限控制:
getfacl file
setfacl -m u:alice:r file
10.3 LSM 与权限扩展
Linux 安全模块(LSM)如 SELinux、AppArmor、Smack 可拦截 inode_permission() 等操作,实施细粒度安全策略。
十一、缓存一致性与刷新机制
11.1 页缓存同步
- 文件修改不会立即反映到磁盘;
- 调用
fsync()/fdatasync()强制同步; - 文件系统驱动实现
->fsync()方法。
11.2 内核同步点
close()时可触发写回;O_SYNC/O_DSYNC方式可实现同步写入;msync()同步 mmap 页面。
十二、调试与工具支持
strace:跟踪系统调用(open, read, write);lsof:列出进程打开的文件;/proc/<pid>/fd/:文件描述符映射;/proc/sys/fs/file-*:查看文件句柄使用上限;fstat():获取打开文件信息;fadvise():优化访问模式(顺序/随机/丢弃);
十三、源码路径参考
| 文件路径 | 功能描述 |
|---|---|
fs/open.c | 实现 open/close 系统调用 |
fs/read_write.c | 实现 read/write 系统调用 |
fs/namei.c | 路径解析(namei 系统) |
fs/file_table.c | 文件描述符分配与管理 |
include/linux/fs.h | file/inode/dentry 等结构定义 |
fs/dcache.c | dentry 缓存管理 |
十四、小结
- open/read/write/close 系统调用通过 VFS 实现;
- 文件由 struct file/inode/dentry 多层结构抽象;
- VFS 提供统一接口,文件系统实现具体逻辑;
- 文件描述符是用户空间与内核文件对象的桥梁;
- 权限检查与缓存管理确保性能与安全并重。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)