我找到了关于如何从内核模块向用户空间发送实时信号的示例代码here
我在内核模块中实现了它,如下所示:
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()。
在用户空间:
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()设置。
问题是用户空间应用程序在等待信号时保持阻塞状态(sigwaitinfo()永远不会返回)。我从控制台看到了printk()调用的输出:
“发送sig 35 val xxxx pid nnnn”
使用正确的信号值(35)和pid。
如果我从用户空间应用程序中调用sigqueue()或者从控制台输入“kill -35 nnnn”,则sigwaitinfo()会成功返回。
我做错了什么?
是否需要从工作队列中调用dmtimer_sendSignal()?
我已尝试将代码设置为SI_KERNEL(无差异),解锁信号(应用程序关闭)和kill_proc_info()(未找到)。
我正在使用来自Critical Link的AM335x SOM上运行的Angstrom发行版。 Angstrom版本v2012.05 - 内核3.2.0-00351-gb80917e
答案 0 :(得分:0)
我遇到了类似的问题,我已经解决了。
在我的例子中,
KernelModule:send_sig_info(SIGRTMIN)
UserProcess:sigaction(SIGRTMIN)
(sa_sigaction处理程序的等待信号)
我真正的问题是“UserProcess的SIGRTMIN”与内核不同。
UserProcess的SIGRTMIN = 34
内核的SIGRTMIN = 32
所以,我将SIGRTMIN的信号编号改为36,我成功修复了它。
您在内核模块中使用了哪个信号编号? SIGRTMIN? 如果您使用SIGRTMIN,我建议您更改信号编号。
感谢。
Jinbum Park。