Linux文件系统的truncate.c源码主要负责实现文件截断相关的核心逻辑,是VFS层与具体文件系统交互处理文件长度调整的关键模块,其实现直接影响文件操作的效率与数据一致性。

truncate.c的整体功能定位
truncate.c中实现了文件截断的基础框架,向上对接系统调用层的ftruncate、truncate等接口,向下调用具体文件系统的截断实现函数。它的核心作用是完成截断操作的通用校验、参数处理,以及协调不同层级的资源释放与元数据更新,避免每个文件系统重复实现相同的通用逻辑。
核心函数实现分析
do_sys_truncate函数
这是系统调用处理的核心入口函数,首先会校验用户传入的路径与长度参数,接着获取目标文件的inode信息,判断当前进程是否有对应的写权限,最后调用具体文件系统的截断接口完成操作。以下是简化后的逻辑代码:
#include <linux/fs.h>
#include <linux/uaccess.h>
static int do_sys_truncate(const char __user *pathname, loff_t length)
{
struct path path;
struct inode *inode;
int error;
// 校验长度合法性,不允许负数
if (length < 0)
return -EINVAL;
// 获取文件路径对应的inode
error = user_path_at(AT_FDCWD, pathname, 0, &path);
if (error)
return error;
inode = path.dentry->d_inode;
// 校验写权限
error = inode_permission(inode, MAY_WRITE);
if (error)
goto out;
// 调用具体文件系统的截断函数
error = inode->i_op->setattr(inode, &newattr);
out:
path_put(&path);
return error;
}
truncate_setsize函数
该函数用于更新inode的文件大小,并通知页缓存层释放超出新长度的页缓存数据,保证文件截断后不会残留无效缓存。代码逻辑如下:
void truncate_setsize(struct inode *inode, loff_t newsize)
{
loff_t oldsize = inode->i_size;
// 更新inode的文件大小
i_size_write(inode, newsize);
// 如果新大小小于旧大小,释放超出部分的页缓存
if (newsize < oldsize)
truncate_pagecache(inode, newsize);
}
与具体文件系统的协作流程
truncate.c本身不直接操作底层存储,而是定义了统一的接口规范,具体文件系统需要实现<code>i_op->setattr</code>接口中的截断逻辑。以ext4文件系统为例,它的ext4_setattr函数会先调用truncate_setsize更新大小,再处理自身的数据块释放、日志更新等专属操作,最后同步inode元数据到磁盘。
关键注意事项
- 截断操作需要保证原子性,避免在操作过程中发生崩溃导致文件元数据与实际数据不一致,因此很多文件系统会在截断前先写日志。
- 处理大文件截断时需要注意loff_t类型的溢出问题,truncate.c中会对长度参数做基础的合法性校验,但具体文件系统也需要做二次校验。
- 截断操作会触发页缓存的释放,因此后续读取截断后的文件区域时,会重新从磁盘加载数据,不会读到旧内容。
总结
truncate.c作为Linux文件系统截断操作的通用层,承担了参数校验、缓存协调、接口规范的作用,降低了具体文件系统的实现复杂度。理解这部分源码,不仅能掌握文件截断的实现逻辑,也能更深入理解Linux VFS层的设计思想,为后续学习其他文件系统操作的内核实现打下基础。
Linuxtruncate_c文件系统源码分析修改时间:2026-07-16 19:12:21