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

内核模块从3.1迁移至3.18:proc_dir_entry使用问题咨询

正确使用 struct proc_dir_entry 在内核3.18版本的方式

首先得明确:fs/proc/internal.h 是内核内部的头文件,绝对不应该在外部模块中引用——它只供proc文件系统自身的代码使用,对外没有稳定性承诺,所以你引用它会提示文件不存在是完全正常的(内核编译环境不会把内部头文件暴露给模块开发者)。

从3.10版本开始,struct proc_dir_entry 被改为不透明类型(opaque type),目的是隐藏内部实现细节,强制开发者使用内核提供的标准API来操作proc目录项,避免模块依赖于内核内部结构体的具体布局(这会导致模块在内核版本升级时极易崩溃)。

下面是3.18版本下操作proc_dir_entry的正确姿势:

1. 创建proc目录/文件的标准API

原来你可能会手动初始化proc_dir_entry结构体,现在必须用这些内核提供的创建函数:

  • 创建proc目录:struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
  • 创建普通proc文件:struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)
  • 创建带私有数据的proc文件:struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops, void *data)
  • 创建自动清理的临时proc文件:struct proc_dir_entry *proc_create_temp(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops, void (*release)(struct proc_dir_entry *), void *data)

2. 设置/获取proc项属性的辅助函数

原来直接访问proc_dir_entry成员(比如->owner、->data)的操作,现在要用对应的内核辅助函数:

  • 设置owner:推荐在创建时通过file_operations的owner字段指定当前模块(THIS_MODULE),也可以用proc_set_user(struct proc_dir_entry *pde, const struct cred *cred)调整权限
  • 获取私有数据:void *proc_get_data(struct proc_dir_entry *pde)
  • 设置私有数据:void proc_set_data(struct proc_dir_entry *pde, void *data, void (*release)(void *))
  • 调整权限:创建时通过proc_create的mode参数指定即可,后续修改尽量避免,若确有需求可使用内核标准的权限修改函数

3. 删除proc目录/文件的正确方式

不再手动释放结构体,而是调用专用删除函数:

  • 删除proc项(文件或目录):void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

注意:如果是用proc_create_data创建并设置了release函数,删除时会自动调用该函数释放私有数据。

示例代码片段

比如创建一个支持读写的proc文件:

#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>

static char proc_buf[256];
static ssize_t proc_read(struct file *file, char __user *buf, size_t count, loff_t *pos) {
    return simple_read_from_buffer(buf, count, pos, proc_buf, strlen(proc_buf));
}

static ssize_t proc_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) {
    if (count >= sizeof(proc_buf))
        return -EINVAL;
    if (copy_from_user(proc_buf, buf, count))
        return -EFAULT;
    proc_buf[count] = '\0';
    return count;
}

static const struct file_operations proc_fops = {
    .owner = THIS_MODULE,
    .read = proc_read,
    .write = proc_write,
};

static struct proc_dir_entry *my_proc_entry;

static int __init my_module_init(void) {
    // 在/proc根目录下创建名为"my_proc"的文件
    my_proc_entry = proc_create("my_proc", 0644, NULL, &proc_fops);
    if (!my_proc_entry)
        return -ENOMEM;
    return 0;
}

static void __exit my_module_exit(void) {
    remove_proc_entry("my_proc", NULL);
}

module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");

关键注意事项

  • 绝对不要尝试直接包含internal.h或者手动解析proc_dir_entry的内部结构——这不仅违反内核开发规范,还会导致你的模块在不同内核版本(甚至同版本的不同配置)下崩溃。
  • 所有操作都要依赖内核公开的proc_fs.h中的API,这些API在稳定版本分支中是向后兼容的。
  • 如果需要实现动态生成内容的proc文件(比如遍历系统状态),可以结合seq_file接口使用,它同样通过proc_create挂载到proc文件系统中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:21:19