How to send a signal from kernel to user space
My kernel module code needs to send a signal [ def. ] to the user land program to pass its execution to the registered signal handler.
I know how to send a signal between two terrestrial user processes, but I cannot find any example on the internet regarding the specified task.
To be specific, my intended task might require an interface like below (once error
! = 1, no line of code int a=10
should be executed):
void __init m_start(){
...
if(error){
send_signal_to_userland_process(SIGILL)
}
int a = 10;
...
}
module_init(m_start())
source to share
You can use, for example, kill_pid
(declared in <linux/sched.h>
) to send a signal to the specified process. To generate parameters for it, see Implementation sys_kill
(defined as SYSCALL_DEFINE2(kill)
in kernel/signal.c
).
Note that it is almost useless to send a signal from the kernel to the current process: kernel code must return before the user-space program ever sees the signal.
source to share
An example I have used in the past to send a signal to user space from a hardware interrupt in kernel space. It was like this:
CORNER 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
Some "includes" and definitions are needed. Basically, you need the PID of the application in user space.
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;
}
The preceding code prepares the signal structure and dispatches it. Keep in mind that you need the PID of the application. In my case, a user-space application submits its PID using the ioctl driver routine:
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 and implement a callback function:
#define SIG_TEST 44
void signalFunction(int n, siginfo_t *info, void *unused) {
printf("received value %d\n", info->si_int);
}
In the main procedure:
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);
Hope this helps, even though the answer is a bit long but easy to understand.
source to share
Your interface breaks the Linux spirit . Don't do this ..... A system call (specifically related to your driver) should only fail with errno
(see syscalls (2) ...); consider eventfd (2) or netlink (7) for such an asynchronous core ↔ userland communication (and expect user code to be able to poll (2) them).
A kernel module could not be loaded. I'm not familiar with the details (never coded any kernel modules), but this hello2.c example assumes that the module's init function may return a non-zero error code on failure.
People really expect signals (which is a complex and painful concept) to behave as described in signal (7) and what you want to do is not appropriate in this picture. Thus, a well-managed kernel module should never send any signal to processes asynchronously .
If your kernel module isn't performing well, your users will get angry and won't use it.
If you want to deploy an experimental kernel (for research purposes, for example), don't expect it to be used a lot; only then could you really break the signal behavior as you intend to do, and you can code things that don't fit into the kernel module image (like adding a new syscall). See also kernelnewbies .
source to share