我需要从内核向用户空间函数发送字符串,而不是特别从用户空间请求它,通过内核中的某些事件触发用户空间中的函数或应用程序。 到目前为止,我已经尝试了一个Ioctl,它在用户空间的init上启动,然后睡觉并继续阅读netlink,但找不到一个好的工作示例。 任何建议或例子都是非常有必要的。
答案 0 :(得分:4)
以下是我的流程如何运作,我也会对任何改进建议感兴趣:
启动用户空间应用程序,该应用程序向内核模块发送自定义命令以注册内核模块信号的用户空间PID。在我的例子中,这是通过写入/ dev / mymodule。内核模块注册PID:
...
printk("registering a new process id to receive signals: %d\n", current->pid);
signal_pid = current->pid;
...
用户空间应用程序还为某些类型的信号注册了内核处理程序。
void local_sig_handler(int signum) {
printf("received a signal from my module\n");
fflush(stdout); }
...
signal(SIGIO, local_sig_handler);
内核模块生成信号
...
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);
}
内核将信号中继到应用程序的处理程序
答案 1 :(得分:2)
你有几个选择:
答案 2 :(得分:0)
我过去使用的一个例子是从内核空间中的硬件中断向用户空间发送信号。
KERNEL SPACE
您必须在发送信号之前准备siginfo和task_struct:
struct siginfo info;
struct task_struct *t;
info.si_signo = SIG_TEST;
info.si_code = SI_QUEUE;
info.si_int = 1234; // Any value you want to send
rcu_read_lock();
并且还可以使用用户空间应用程序PID查找任务。您必须通过write或ioctl操作将它从用户空间发送到内核空间。
t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
然后你可以发送信号。
rcu_read_unlock();
send_sig_info(SIG_TEST, &info, t);
我在此省略,但您必须检查每个操作的结果。
前面的代码准备信号结构并发送它。请记住,您需要应用程序的PID。在我的情况下,来自用户空间的应用程序通过ioctl驱动程序发送其PID。
USER SPACE
您必须定义并实现回调函数:
void signalFunction(int n, siginfo_t *info, void *unused) {
.....
.....
}
在主要程序中:
struct sigaction sig;
sig.sa_sigaction = signalFunction; // Callback function
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig, NULL);
我希望它有所帮助。