linux | 使用proc节点实现内核↔用户态双向完整通信

linux | 使用proc节点实现内核↔用户态双向完整通信


时间:2026年7月24日12:03:09


使用 proc 节点实现内核↔用户态双向完整通信

一、核心原理

proc 是 Linux 虚拟文件系统,驱动创建自定义 /proc/xxx 节点,注册read、write 回调

  1. 用户态读节点 → 触发内核proc_read,内核把数据发给用户;
  2. 用户态写节点 → 触发内核proc_write,用户把数据传给内核; 依靠这两个回调,完成双向数据收发。

两种通信架构(推荐方案 2:一问一答,无数据冲突)

  1. 单缓冲区单向收发(简易):一个缓冲区存内核下发指令,用户写完应答覆盖;
  2. 双缓冲区分离收发(标准商用,你业务用)
    1. tx_buf:内核→用户 指令缓冲区(内核写,用户读)
    2. rx_buf:用户→内核 应答 / 参数缓冲区(用户写,内核读)

二、完整内核驱动代码(双向通信,支持指令、参数读写)

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

#define PROC_NAME "udisk_comm"
#define BUF_MAX 256

// 双缓冲区:分离内核下发、用户应答,避免覆盖冲突
static char g_kernel_tx[BUF_MAX] = {
   
   0};  // 内核发给用户的指令
static char g_user_rx[BUF_MAX] = {
   
   0};    // 用户发给内核的应答/参数
static struct proc_dir_entry *g_proc_node;

// ===================== 用户态读取节点时触发:内核 → 用户 =====================
static ssize_t proc_read_cb(struct file *file, char __user *usr_buf, size_t len, loff_t *pos)
{
   
   
    char *send_data = g_kernel_tx;
    size_t data_len = strlen(send_data);

    // 偏移超过数据长度,无数据返回
    if (*pos >= data_len)
        return 0;

    data_len -= *pos;
    if (data_len > len)
        data_len = len;

    // 内核数据拷贝到用户空间
    if (copy_to_user(usr_buf, send_data + *pos, data_len))
        return -EFAULT;

    *pos += data_len;
    return data_len;
}

// ===================== 用户态写入节点时触发:用户 → 内核 =====================
static ssize_t proc_write_cb(struct file *file, const char __user *usr_buf, size_t len, loff_t *pos)
{
   
   
    char tmp_buf[BUF_MAX] = {
   
   0};
    if (len >= BUF_MAX)
        len = BUF_MAX - 1;

    // 用户空间数据拷贝到内核临时缓存
    if (copy_from_user(tmp_buf, usr_buf, len))
        return -EFAULT;
    tmp_buf[len] = '\0';

    // 用户写入的数据存入应答缓冲区,内核可轮询读取
    strncpy(g_user_rx, tmp_buf, BUF_MAX - 1);
    printk("内核收到用户态数据:%s\n", g_user_rx);

    return len;
}

// proc文件操作绑定读写回调
static const struct proc_ops proc_fops = {
   
   
    .proc_read  = proc_read_cb,
    .proc_write = proc_write_cb,
};

// 对外API1:内核下发指令给用户态(写tx缓冲区)
void kernel_send_cmd_to_user(const char *cmd_str)
{
   
   
    memset(g_kernel_tx, 0, sizeof(g_kernel_tx));
    strncpy(g_kernel_tx, cmd_str, BUF_MAX - 1);
    printk("内核下发指令:%s\n", g_kernel_tx);
}

// 对外API2:内核读取用户态上报的应答数据
int kernel_read_user_reply(char *out_buf, int buf_len)
{
   
   
    if (strlen(g_user_rx) == 0)
        return -ENODATA;

    memset(out_buf, 0, buf_len);
    strncpy(out_buf, g_user_rx, buf_len - 1);
    // 读取完成清空应答缓冲区,等待下一次上报
    memset(g_user_rx, 0, sizeof(g_user_rx))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值