关键词:VFS、文件描述符、struct file、struct inode、open、read、write、close、dentry、权限校验、file_operations、O_NOATIME、权限继承
在 Linux 中,几乎一切资源都可以通过“文件”的形式访问。文件访问不仅涵盖传统的磁盘文件,还包括设备、管道、socket、内存映射对象等。
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);
open() ──> sys_open() ──> do_sys_open()
└─> do_filp_open()
└─> namei 解析
└─> permission 检查
└─> 创建 struct file / struct dentry / struct inode
整个文件访问路径经过 VFS(Virtual File System),它为所有具体文件系统(如 ext4、xfs)提供统一抽象接口。
表示进程打开的一个“活跃”文件(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
各自独立。表示文件的元信息(持久存在于文件系统中):
struct inode {
umode_t i_mode;
struct file_operations *i_fop;
unsigned long i_ino; // inode 编号
struct super_block *i_sb;
...
};
路径名与 inode 的绑定:
struct dentry {
struct inode *d_inode;
struct dentry *d_parent;
struct qstr d_name;
...
};
文件描述符是用户空间表示“打开文件”的整数编号,其实是进程文件描述表的下标。
struct files_struct {
struct file **fdt; // file descriptor table
};
每个进程拥有一份 files_struct
,记录其打开的所有文件。
get_unused_fd_flags()
:分配描述符;fd_install()
:将 struct file 与 fd 绑定;sys_close(fd)
→ filp_close()
;SYSCALL_DEFINE3(open, const char __user *, filename,
int, flags, umode_t, mode)
sys_open()
└── do_sys_open()
└── get_unused_fd()
└── do_filp_open()
└── open_namei() // 路径解析
└── inode_permission()
└── alloc_file()
└── fd_install()
O_CREAT
:若文件不存在则创建;O_TRUNC
:打开时清空文件;O_APPEND
:每次写入追加;O_DIRECTORY
:仅允许打开目录;O_NOATIME
:不更新访问时间。do_filp_open()
调用 path_openat()
执行路径查找:
path_lookupat()
└── walk_component() // 按“/”逐级查找
└── dcache 查找 dentry
└── 最终找到目标 inode
根据 inode 上的权限位与当前进程身份(UID/GID)判断是否允许访问。
bool inode_permission(struct inode *inode, int mask);
sys_read()
└── vfs_read()
└── file->f_op->read_iter()
└── generic_file_read_iter()
└── filemap_read() // 页缓存操作
sys_write()
└── vfs_write()
└── file->f_op->write_iter()
└── generic_file_write_iter()
└── filemap_write()
sys_close()
└── filp_close()
└── fput()
└── file->f_op->release()
O_CLOEXEC
文件描述符默认会保留;fcntl(fd, F_SETFD, FD_CLOEXEC)
设置关闭标志。文件系统驱动实现 file_operations
,VFS 会在 open() 时设置 file->f_op
指针:
struct file_operations {
ssize_t (*read) (...);
ssize_t (*write) (...);
int (*open) (...);
int (*release) (...);
int (*mmap) (...);
...
};
支持更细粒度的权限控制:
getfacl file
setfacl -m u:alice:r file
Linux 安全模块(LSM)如 SELinux、AppArmor、Smack 可拦截 inode_permission()
等操作,实施细粒度安全策略。
fsync()
/ fdatasync()
强制同步;->fsync()
方法。close()
时可触发写回;O_SYNC
/ O_DSYNC
方式可实现同步写入;msync()
同步 mmap 页面。strace
:跟踪系统调用(open, read, write);lsof
:列出进程打开的文件;/proc//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 缓存管理 |