You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在内核代码中删除/tmp目录文件?内核驱动文件卸载后未删除怎么办?

在内核代码中删除文件的解决方案

一、内核态删除/tmp目录下任意文件的通用方法

在内核空间里,咱们没法直接调用用户态的unlink()系统调用,得用VFS(虚拟文件系统)层的vfs_unlink()函数来完成删除操作。具体步骤如下:

  1. 解析文件路径:用kern_path()把用户可读的文件路径转换成内核能处理的struct path结构,这个结构包含了文件的目录项(dentry)和挂载信息(vfsmount)。
  2. 执行删除操作:调用vfs_unlink(),需要传入父目录的inode、目标文件的dentry,属性参数一般传NULL就行。
  3. 清理资源:操作完成后用path_put()释放struct path的引用,避免内存泄漏。

代码示例

#include <linux/fs.h>
#include <linux/sched.h>

int delete_tmp_file(const char *filename) {
    struct path path;
    char full_path[64];
    int ret;

    // 拼接/tmp下的完整文件路径
    snprintf(full_path, sizeof(full_path), "/tmp/%s", filename);

    // 解析路径,LOOKUP_FOLLOW表示自动跟随符号链接
    ret = kern_path(full_path, LOOKUP_FOLLOW, &path);
    if (ret != 0) {
        pr_err("Failed to resolve path %s: error %d\n", full_path, ret);
        return ret;
    }

    // 可选:判断目标是否为普通文件,避免误删目录
    if (!S_ISREG(path.dentry->d_inode->i_mode)) {
        pr_err("%s is not a regular file\n", full_path);
        path_put(&path);
        return -EINVAL;
    }

    // 调用vfs_unlink执行删除
    ret = vfs_unlink(path.dentry->d_parent->d_inode, path.dentry, NULL);
    if (ret != 0) {
        pr_err("Failed to delete %s: error %d\n", full_path, ret);
    } else {
        pr_info("Successfully deleted %s\n", full_path);
    }

    // 释放路径引用
    path_put(&path);
    return ret;
}

关键注意事项

  • 上下文限制:kern_path()和vfs_unlink()都可能触发睡眠,绝对不能在中断上下文、持有自旋锁的原子上下文里调用这些函数。
  • 安全策略:内核态操作权限很高,但如果系统开了SELinux/AppArmor这类安全模块,可能需要额外配置策略才能让模块顺利删除文件。
  • 错误处理:一定要检查每个函数的返回值,比如文件不存在、权限不足这些情况都要妥善处理,别让模块崩了。

二、模块卸载时删除已创建的/tmp/output文件

你用filp_open()创建文件后,filp_close()只是关闭文件句柄,并不会删除文件本身。要实现模块卸载时自动删除它,只需要在模块的exit函数里加入删除逻辑就行。

完整模块示例片段

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/uaccess.h>

static struct file *output_file;

static int __init my_module_init(void) {
    // 创建并打开/tmp/output,权限设为0644
    output_file = filp_open("/tmp/output", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (IS_ERR(output_file)) {
        pr_err("Failed to open /tmp/output: %ld\n", PTR_ERR(output_file));
        return PTR_ERR(output_file);
    }

    // 可选:写入内容到文件
    // char buf[] = "Hello from kernel module!";
    // kernel_write(output_file, buf, sizeof(buf)-1, &output_file->f_pos);

    pr_info("Module loaded, /tmp/output created\n");
    return 0;
}

static void __exit my_module_exit(void) {
    // 先关闭文件句柄(如果之前没关闭)
    if (output_file && !IS_ERR(output_file)) {
        filp_close(output_file, NULL);
        output_file = NULL;
    }

    // 删除/tmp/output文件
    struct path path;
    int ret = kern_path("/tmp/output", LOOKUP_FOLLOW, &path);
    if (ret == 0) {
        ret = vfs_unlink(path.dentry->d_parent->d_inode, path.dentry, NULL);
        if (ret == 0) {
            pr_info("/tmp/output deleted on module unload\n");
        } else {
            pr_err("Failed to delete /tmp/output: %d\n", ret);
        }
        path_put(&path);
    } else {
        pr_warn("/tmp/output does not exist, skip deletion\n");
    }

    pr_info("Module unloaded\n");
}

module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Example module to create and auto-delete /tmp/output");

额外提示

  • 如果模块运行中会多次操作这个文件,可以保存文件的struct path或dentry引用(注意维护引用计数),不用每次删除都重新解析路径。
  • 模块卸载时一定要清理所有资源,包括文件句柄、动态分配的内存等,避免留下资源泄漏的隐患。

内容的提问来源于stack exchange,提问作者arry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:05:17