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

Linux字符驱动中如何为不同读取进程返回不同数据?

Linux字符驱动:为不同进程返回对应键值的实现方案

问题背景

开发一款Linux字符驱动,目标是实现键值存储功能:不同进程向/dev/key写入查询键后,读取/dev/value时能返回对应的值。核心需求是驱动需跟踪每个进程的查询键,但不清楚如何获取当前执行读写操作的进程信息,误以为struct file结构体中包含相关字段,实际未找到。

驱动接口使用示例:

# 终端1执行
echo "test" > /dev/key # 告知驱动要查询的键
cat /dev/value # 读取与"test"关联的值
# 终端2执行
echo "other_key" > /dev/key
cat /dev/value

实现方法

1. 通过current宏获取当前进程标识

Linux内核提供current宏,直接指向当前正在执行的进程描述符struct task_struct,可在驱动的read/write回调中直接调用,获取PID、线程ID等唯一标识来区分不同进程:

#include <linux/sched.h>

ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
    // 获取用户空间可见的进程ID(线程组ID)
    pid_t proc_id = current->tgid;
    // 获取内核级线程ID
    pid_t thread_id = current->pid;
    
    // 用proc_id作为键,将用户写入的key存储到内核哈希表或其他结构中
    // ...
    return count;
}

2. 利用struct file的private_data存储进程上下文

struct file本身没有进程标识字段,但可以在进程打开设备文件时(open回调),为每个进程分配独立的上下文结构体,挂载到filp->private_data上,后续读写操作直接从该字段获取进程对应的查询键:

// 自定义上下文结构体,保存进程ID和对应的查询键
struct proc_key_ctx {
    pid_t proc_id;
    char query_key[64];
};

// 设备open回调:为进程分配上下文
int key_open(struct inode *inode, struct file *filp) {
    struct proc_key_ctx *ctx = kmalloc(sizeof(struct proc_key_ctx), GFP_KERNEL);
    if (!ctx) return -ENOMEM;
    
    ctx->proc_id = current->tgid;
    memset(ctx->query_key, 0, sizeof(ctx->query_key));
    filp->private_data = ctx;
    
    return 0;
}

// 设备write回调:保存用户写入的查询键到上下文
ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
    struct proc_key_ctx *ctx = filp->private_data;
    size_t copy_len = min(count, sizeof(ctx->query_key) - 1);
    
    if (copy_from_user(ctx->query_key, buf, copy_len)) {
        return -EFAULT;
    }
    return count;
}

// 设备release回调:释放上下文内存,避免泄漏
int key_release(struct inode *inode, struct file *filp) {
    kfree(filp->private_data);
    return 0;
}

在/dev/value的read回调中,同样通过current->tgid匹配对应的上下文,取出查询键后返回关联的值即可。

3. 关键注意事项

  • 内存管理:必须在release回调中释放private_data分配的内存,防止进程退出后内存泄漏。
  • 线程区分:如果需要区分同一进程内的不同线程,使用current->pid(内核线程ID)而非current->tgid(用户空间进程ID)。
  • 键值存储:内核中可使用哈希表(如struct hlist_head)或idr结构,以进程ID为键,存储查询键与对应值的映射关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:40:58