本页目录
VFS 进阶
覆盖: page cache 与 VFS 交互 → inode 状态机 → file locking (POSIX/OFD) → fsync/fdatasync 保证 → sendfile/splice/vmsplice 零拷贝 内核版本: 2.6 ~ 6.x
Page Cache 与 VFS 交互
inode 与 address_space 的关系
// inode->i_mapping 指向该文件的 page cache
// 这是一个 address_space 结构,管理该文件在内存中的所有缓存页面
// 大多数 inode->i_mapping 指向内嵌的 inode->i_data:
;
// 对于块设备的裸读写:
;
inode 状态机
// include/linux/fs.h
// inode 生命周期:
// alloc_inode() → I_NEW
// insert_inode_locked() → 加入 inode hash
// unlock_new_inode() → 清 I_NEW, 唤醒等待者
// ... 活跃期 ...
// iput() → i_count == 0 → evict() → I_FREEING → destroy_inode()
File Locking
POSIX Lock (fcntl)
// POSIX advisory/强制锁
;
; // 非阻塞
; // 阻塞等待
; // 查询
// 实现: fs/locks.c
// 锁挂在 inode->i_flctx (file_lock_context)
// 检测冲突: posix_locks_conflict() → 遍历 conflict chain
// 进程关闭 fd → 自动释放所有 POSIX lock (无论 fork 关系)
OFD Lock (Open File Description, 3.15+)
// POSIX lock 的问题: 同一个进程的不同 fd 不能各自持锁
// OFD lock 解决: 锁挂在 "打开文件描述" (file) 上, 不是进程
;
// fork 场景:
// POSIX: 子进程继承父进程的锁 (因为同一个 PID)
// OFD: 子进程不继承 (不同 file, 不一定)
FLOCK (BSD Lock)
; // 共享
; // 排他
; // 解锁
// 与 POSIX lock 的区别:
// FLOCK 挂在 file 上 (不是 inode, 不是进程)
// 同一个 file 的多次 flock 自动关联
// fork 继承 flock (因为 file 共享)
// 仅 advisory (没有强制锁)
fsync / fdatasync: 持久性保证
// fs/sync.c
→ →
├─ // 1. 回写 dirty page cache
│ └─ →
│ → 每个 dirty folio → a_ops->
│ └─ // 等回写完成
│
└─
└─ f_op-> // 2. 文件系统: 写 journal / 强制 flush
→ ext4: jbd2 提交事务 + blkdev_issue_flush
→ XFS: 强制日志刷盘 + flush
→ NFS: COMMIT 操作
// fdatasync (FDATASYNC): 只刷数据部分 (不刷 i_atime/i_mtime)
// → vfs_fsync_range(file, start, end, 1)
// → 文件系统可以跳过时间戳同步
零拷贝: sendfile / splice / vmsplice
// sendfile(): 文件 → socket, 不经过用户空间
→
└─ → pipe buffer ← 文件内容
└─ → pipe buffer → socket
// splice(): 两个 fd 之间管道传输 (内核空间)
; // fd → pipe
; // pipe → fd
// vmsplice(): 用户空间内存 → pipe (与 splice 配合)
;
// 用户内存的页被"送给"内核 (不再是用户态的了)
// → pipe 引用这些页 → splice 到 socket → 零拷贝发网卡
DMA 零拷贝路线
调试
# inode cache 统计
# 查看进程的文件锁
# 追踪 fsync 行为
参考与延伸
- 内核文档:
Documentation/filesystems/locks.rst,Documentation/filesystems/vfs.rst - LWN:
- "Better file locking with OFD locks" (lwn.net/Articles/586904/)
- "Splice and sendfile" (lwn.net/Articles/178199/)
- 源码文件:
fs/locks.c— POSIX/OFD/FLOCK 实现fs/sync.c— fsync/fdatasyncfs/splice.c— splice/sendfile/vmsplicefs/inode.c— inode 生命周期
关键词: VFS, inode state, POSIX lock, OFD lock, FLOCK, fsync, fdatasync, sendfile, splice, zero-copy