用内核触发用户空间

Gsr*_*ati 3 linux-kernel embedded-linux

我需要从内核向用户空间函数发送一个字符串,而不需要特别从用户空间请求它,有点通过内核中的某个事件触发用户空间中的函数或应用程序。到目前为止,我已经尝试了一个 Ioctl,它从用户空间中的 init 开始,然后休眠并继续阅读有关 netlink 的内容,但找不到一个很好的工作示例。任何建议或示例将非常感谢。

ems*_*rth 5

这是我的流程的工作方式,我也对任何改进建议感兴趣:

  1. 启动内核模块
  2. 启动用户空间应用程序,它向内核模块发送自定义命令,为内核模块信号注册用户空间 PID。就我而言,这是通过写入 /dev/mymodule 来实现的。内核模块注册PID:

    ...
    printk("registering a new process id to receive signals: %d\n", current->pid);
    signal_pid = current->pid;
    ...
    
    Run Code Online (Sandbox Code Playgroud)

    用户空间应用程序还为某些类型的信号向内核注册一个处理程序。

    void local_sig_handler(int signum) {
            printf("received a signal from my module\n");
            fflush(stdout); }
    ...
    signal(SIGIO, local_sig_handler);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 内核模块产生信号

    ...
    struct siginfo info;
    struct task_struct *t;
    info.si_signo=SIGIO;
    info.si_int=1;
    info.si_code = SI_QUEUE;        
    
    printk("<1>IRQ received: %d\n", irq);
    printk("<1>searching for task id: %d\n", signal_pid);
    
    t= pid_task(find_vpid(signal_pid),PIDTYPE_PID);//user_pid has been fetched successfully
    
    if(t == NULL){
            printk("<1>no such pid, cannot send signal\n");
    } else {
            printk("<1>found the task, sending signal\n");
            send_sig_info(SIGIO, &info, t);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 内核将信号中继到应用程序的处理程序

  • 您不应该使用 PID 来识别内核中的进程。该进程可以退出,另一个进程会重新使用该 PID。相反,您应该为进程使用指向 `task_struct` 的指针(而不是在注册时存储 `current-&gt;pid`,只存储 `current`)。 (5认同)