从内核模块向用户空间发送实时信号失败 [英] Sending realtime signal from a kernel module to user space fails
问题描述
I found example code on how to send a realtime signal from a kernel module to user space here
我在内核模块中实现了它,如下所示:
I implemented it in the kernel module as shown below:
static int dmtimer_sendSignal(int val, int id, int sig)
{
struct siginfo info;
struct task_struct *t;
int ret;
ret = 0;
if ((id > 0) && (sig > 0))
{
/* send the signal */
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = sig;
info.si_code = SI_QUEUE; // 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_int = val; //real time signals may have 32 bits of data.
info._sifields._rt._sigval.sival_int = val;
info.si_errno = 0;
rcu_read_lock();
// t = find_task_by_pid_type(PIDTYPE_PID, pid); //find the task_struct associated with this pid
t = pid_task(find_pid_ns(id, &init_pid_ns), PIDTYPE_PID);
if(t == NULL)
{
printk("no such pid\n");
rcu_read_unlock();
return -ENODEV;
}
ret = send_sig_info(sig, &info, t); //send the signal
rcu_read_unlock();
if (ret < 0)
{
printk("error sending signal\n");
return ret;
}
else
printk("Send sig %d val %d pid %d\n", sig, val, id);
}
return ret;
}
从模块中的中断服务例程调用功能dmtimer_sendSignal().
The function dmtimer_sendSignal() is called from an interrupt service routine in the module.
在用户空间:
main()
{
sigemptyset (&alarm_sig);
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
sigaddset (&alarm_sig, i);
sigprocmask (SIG_BLOCK, &alarm_sig, NULL);
}
void * DATA_taskInput(void *pArg)
{
siginfo_t info;
int32_t input;
sigset_t input_sig;
int fd;
// Create digital input event
sig = SIGRTMIN+1;
sigemptyset(&gSig_input);
sigaddset(&gSig_input, sig);
// Set real time signal number for module to use
if (TIMER_setParm(PARM_SIGRT, SIGRTMIN + 1 ) < 0)
error(0, errno, "THREADS_events() called TIMER_setParm():");
// Set PID in module
TIMER_setParm(PARM_PID, getpid());
fd = signalfd(-1, &gSig_input, 0);
while(!gQuitInput)
{
sigwaitinfo(&gSig_input, &info); // digital input event
// read(fd, &info, sizeof(info));
printf("val = 0x%x\n", info.si_int);
}
close(fd);
printf("DATA_taskInput() end.\n");
return NULL;
} // end: DATA_taskInput
用户空间应用程序pid和实时信号号作为模块参数实现,并由用户空间应用程序使用TIMER_setParm()进行设置.
The user space application pid, and realtime signal number are implemented as module parameters and are set by the user space application, with TIMER_setParm().
问题是用户空间应用程序保持阻塞状态,等待信号(sigwaitinfo()从不返回).我从控制台看到printk()调用的输出:
The problem is the user space application stays blocked waiting on the signal (sigwaitinfo() never returns). I see from the console the output of the printk() call:
发送sig 35 val xxxx pid nnnn"
"Send sig 35 val xxxx pid nnnn"
具有正确的信号(35)和pid值.
with the correct values for the signal (35) and pid.
如果我从用户空间应用程序中调用sigqueue()或从控制台输入"kill -35 nnnn",则sigwaitinfo()成功返回.
sigwaitinfo() returns successfully if I call sigqueue() from within the user space application or if I enter "kill -35 nnnn" from the console.
我在做什么错了?
是否需要从工作队列中调用dmtimer_sendSignal()?
Does dmtimer_sendSignal() need to be called from a work queue?
我尝试将代码设置为SI_KERNEL(无差异),解除对信号的阻止(应用程序关闭)和kill_proc_info()(未找到).
I have tried setting the code to SI_KERNEL (no difference), unblocking the signals (applications closes), and kill_proc_info() (not found).
我正在使用在Critical Link的AM335x SOM上运行的Angstrom发行版.Angstrom版本v2012.05-内核3.2.0-00351-gb80917e
I am using an Angstrom distribution running on a AM335x SOM from Critical Link. Angstrom version v2012.05 - Kernel 3.2.0-00351-gb80917e
推荐答案
我遇到了与您类似的问题,并且已经解决.
I had a similar problem to yours and I've solved it.
在我的示例中,
-
内核模块:
send_sig_info(SIGRTMIN)
UserProcess: sigaction(SIGRTMIN)
(由sa_sigaction处理程序等待信号)
UserProcess: sigaction(SIGRTMIN)
(Wait signal by sa_sigaction handler)
我真正的问题是"UserProcess的SIGRTMIN"与内核不同.
and my real problem is that "SIGRTMIN of UserProcess" is different from Kernel.
-
UserProcess的SIGRTMIN = 34
SIGRTMIN of UserProcess = 34
内核的SIGRTMIN = 32
SIGRTMIN of Kernel = 32
因此,我将信号号从SIGRTMIN更改为36,并成功修复了该信号.
So, I changed signal number from SIGRTMIN to 36 and I succeeded in fixing it.
您在内核模块中使用了哪个信号号?SIGRTMIN ??如果使用SIGRTMIN,建议您更改信号编号.
Which signal number did you use in your kernel module?? SIGRTMIN?? If you use SIGRTMIN, I recommend you to change signal number.
谢谢.
金本公园.
这篇关于从内核模块向用户空间发送实时信号失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!