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

如何从内核模块向用户态应用共享64位整数?

内核模块向用户态共享64位整数的实现方案

问题背景

在中断处理流程中,需要将读取到的64位寄存器值传递给用户态进程,尝试使用信号时遇到用户态无法直接访问内核内存的问题。

解决方案:利用实时信号传递拆分后的64位值

实时信号(SIGRTMIN至SIGRTMAX)支持通过siginfo_t结构体携带额外数据,可将64位值拆分为两个32位部分,分别存入该结构体的可访问字段,避免内核内存直接暴露给用户态。

内核端实现代码

#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/uaccess.h>

// 假设在中断处理或内核函数中调用此逻辑
int send_64bit_to_user(struct task_struct *task, uint64_t value_to_send) {
    struct siginfo info;
    memset(&info, 0, sizeof(info)); // 初始化结构体,避免未定义行为

    info.si_signo = SIGRTMIN;          // 使用实时信号
    info.si_code = SI_QUEUE;           // 标记为队列式信号发送
    info.si_pid = current->pid;        // 发送进程PID
    info.si_uid = current_uid().val;   // 发送进程UID

    // 拆分64位值为两个32位部分
    info.si_lower = (uint32_t)(value_to_send & 0xFFFFFFFF); // 低32位
    info.si_upper = (uint32_t)(value_to_send >> 32);        // 高32位

    // 发送信号到目标用户态进程
    int ret = send_sig_info(SIGRTMIN, &info, task);
    if (ret < 0) {
        printk(KERN_ALERT "send_sig_info failed: %d\n", -ret);
        return ret;
    }
    return 0;
}

用户态接收代码

用户态需通过sigaction注册带siginfo_t支持的信号处理函数,拼接回64位值:

#include <stdio.h>
#include <signal.h>
#include <stdint.h>
#include <unistd.h>

void rt_sig_handler(int signo, siginfo_t *info, void *unused) {
    if (signo != SIGRTMIN) return;

    // 拼接32位字段为64位值
    uint64_t received_value = ((uint64_t)info->si_upper << 32) | info->si_lower;
    printf("Received 64-bit value from kernel: 0x%lx\n", received_value);
}

int main() {
    struct sigaction sa;
    sa.sa_sigaction = rt_sig_handler;
    sa.sa_flags = SA_SIGINFO; // 启用siginfo_t传递
    sigemptyset(&sa.sa_mask);

    if (sigaction(SIGRTMIN, &sa, NULL) == -1) {
        perror("Failed to set signal handler");
        return 1;
    }

    printf("Waiting for kernel signal...\n");
    while (1) {
        pause(); // 阻塞等待信号
    }

    return 0;
}

关键注意事项

  • 实时信号特性:实时信号支持排队,不会像普通信号那样丢失,适合中断这类可能频繁触发的场景。
  • 进程指针获取:确保目标进程的task_struct指针正确,可通过PID查找:struct task_struct *task = pid_task(find_vpid(target_pid), PIDTYPE_PID);
  • 信号队列限制:内核实时信号队列长度有限(可通过/proc/sys/kernel/rtsig-max调整),高频中断场景下需注意避免信号溢出。
  • 字节序兼容:同一架构下内核与用户态字节序一致,无需额外处理跨字节序问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:44:53