linux-kernel - 如何从内核向用户空间发送信号

标签 linux-kernel signals

我的内核模块代码需要发送信号 [ def. ] 到用户平台程序,将其执行转移到注册的信号处理程序。

我知道如何在两个用户登陆进程之间发送信号,但我在网上找不到关于上述任务的任何示例。

具体来说,我的预期任务可能需要如下界面(一旦 error != 1,代码行 int a=10 不应执行):

void __init m_start(){
    ...
    if(error){
        send_signal_to_userland_process(SIGILL)
    }
    int a = 10;
    ...
}

module_init(m_start())

最佳答案

我过去使用的一个示例,用于从内核空间的硬件中断向用户空间发送信号。就是这样:

KERNEL SPACE


#include <asm/siginfo.h>    //siginfo
#include <linux/rcupdate.h> //rcu_read_lock
#include <linux/sched.h>    //find_task_by_pid_type

static int pid; // Stores application PID in user space

#define SIG_TEST 44

需要一些“包含”和定义。基本上,您需要用户空间中应用程序的 PID。
struct siginfo info;
struct task_struct *t;

memset(&info, 0, sizeof(struct siginfo));
info.si_signo = SIG_TEST;
// This is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space,    and kernel space should use SI_KERNEL. 
// But if SI_KERNEL is used the real_time data  is not delivered to the user space signal handler function. */
info.si_code = SI_QUEUE;
// real time signals may have 32 bits of data.
info.si_int = 1234; // Any value you want to send
rcu_read_lock();
// find the task with that pid
t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
if (t != NULL) {
    rcu_read_unlock();      
    if (send_sig_info(SIG_TEST, &info, t) < 0) // send signal
        printk("send_sig_info error\n");
} else {
     printk("pid_task error\n");
     rcu_read_unlock();
    //return -ENODEV;
}

前面的代码准备好信号结构并发送它。请记住,您需要应用程序的 PID。在我的例子中,来自用户空间的应用程序通过 ioctl 驱动程序发送它的 PID:
static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    ioctl_arg_t args;
    switch (cmd) {
        case IOCTL_SET_VARIABLES:
              if (copy_from_user(&args, (ioctl_arg_t *)arg, sizeof(ioctl_arg_t))) return -EACCES;
              pid = args.pid;
        break;

USER SPACE



定义并实现回调函数:
#define SIG_TEST 44

void signalFunction(int n, siginfo_t *info, void *unused) {
    printf("received value %d\n", info->si_int);
}

在主要程序中:
int  fd = open("/dev/YourModule", O_RDWR); 
if (fd < 0) return -1;

args.pid       = getpid();
ioctl(fd, IOCTL_SET_VARIABLES, &args); // send the our PID as argument

struct sigaction sig;

sig.sa_sigaction = signalFunction; // Callback function
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig, NULL);

我希望它有所帮助,尽管答案有点长,但很容易理解。

关于linux-kernel - 如何从内核向用户空间发送信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31646466/

相关文章:

c++ - Qt/embedded 中的手动事件处理(不使用 QApplication :exec() )

http - 向当前 Golang 进程发送自定义信号

matlab - 使用傅立叶变换和 MATLAB 过滤信号噪声

c - 为什么在中断处理程序中使用自旋锁

terminal - 命令输出 ELF : zR: Error

c - 在条件变量未发出信号时设置 settimer() 和 SIGALRM

c - 在使用之前对结构进行 memset 是一种很好的风格吗?

rust - 如何优雅地关闭 warp 服务器?

linux - linux下只有中断向量能识别中断源吗?

linux - 在 Linux 系统上保留大页面