问题
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;
}
The function dmtimer_sendSignal() is called from an interrupt service routine in the module.
In user space:
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
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().
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:
"Send sig 35 val xxxx pid nnnn"
with the correct values for the signal (35) and pid.
sigwaitinfo() returns successfully if I call sigqueue() from within the user space application or if I enter "kill -35 nnnn" from the console.
What am I doing wrong?
Does dmtimer_sendSignal() need to be called from a work queue?
I have tried setting the code to SI_KERNEL (no difference), unblocking the signals (applications closes), and kill_proc_info() (not found).
I am using an Angstrom distribution running on a AM335x SOM from Critical Link. Angstrom version v2012.05 - Kernel 3.2.0-00351-gb80917e
回答1:
I had a similar problem to yours and I've solved it.
In my example,
KernelModule:
send_sig_info(SIGRTMIN)
UserProcess:
sigaction(SIGRTMIN)
(Wait signal by sa_sigaction handler)
and my real problem is that "SIGRTMIN of UserProcess" is different from Kernel.
SIGRTMIN of UserProcess = 34
SIGRTMIN of Kernel = 32
So, I changed signal number from SIGRTMIN to 36 and I succeeded in fixing it.
Which signal number did you use in your kernel module?? SIGRTMIN?? If you use SIGRTMIN, I recommend you to change signal number.
Thanks.
Jinbum Park.
来源:https://stackoverflow.com/questions/33041199/sending-realtime-signal-from-a-kernel-module-to-user-space-fails