By liran bh | 5/16/2016 | Linux Kernel & Internals

Sending Signal to User space

Kernel Code:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/siginfo.h>    //siginfo
#include <linux/rcupdate.h>    //rcu_read_lock
#include <linux/sched.h>    //find_task_by_pid_type
#include <linux/debugfs.h>
#include <linux/uaccess.h>
 
#define SIG_TEST 44    // we choose 44 as our signal number (real-time signals are in the range of 33 to 64)
 
struct dentry *file;
 
static ssize_t write_pid(struct file *file, const char __user *buf,
                                size_t count, loff_t *ppos)
{
    char mybuf[10];
    int pid = 0;
    int ret;
    struct siginfo info;
    struct task_struct *t;
    /* read the value from user space */
    if(count > 10)
        return -EINVAL;
    copy_from_user(mybuf, buf, count);
    sscanf(mybuf, "%d", &pid);
    printk("pid = %d\n", pid);
 
    /* send the signal */
    memset(&info, 0, sizeof(struct siginfo));
    info.si_signo = SIG_TEST;
    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 = 1234;          //real time signals may have 32 bits of data.
 
    rcu_read_lock();
    t = find_task_by_vpid(pid);  //find the task_struct associated with this pid
    if(t == NULL){
        printk("no such pid\n");
        rcu_read_unlock();
        return -ENODEV;
    }
    rcu_read_unlock();
    ret = send_sig_info(SIG_TEST, &info, t);    //send the signal
    if (ret < 0) {
        printk("error sending signal\n");
        return ret;
    }
    return count;
}
 
static const struct file_operations my_fops = {
    .write = write_pid,
};
 
static int __init signalexample_module_init(void)
{
    /* we need to know the pid of the user space process
      * -> we use debugfs for this. As soon as a pid is written to 
      * this file, a signal is sent to that pid
      */
    /* only root can write to this file (no read) */
    file = debugfs_create_file("signalconfpid", 0200, NULL, NULL, &my_fops);
    return 0;
}
static void __exit signalexample_module_exit(void)
{
    debugfs_remove(file);
 
}
 
module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");

 

User Code:

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
 
#define SIG_TEST 44 /* we define our own signal, hard coded since SIGRTMIN is different in user and in kernel space */ 
 
void receiveData(int n, siginfo_t *info, void *unused) {
    printf("received value %i\n", info->si_int);
}
 
int main ( int argc, char **argv )
{
    int configfd;
    char buf[10];
    /* setup the signal handler for SIG_TEST 
      * SA_SIGINFO -> we want the signal handler function with 3 arguments
      */
    struct sigaction sig;
    sig.sa_sigaction = receiveData;
    sig.sa_flags = SA_SIGINFO;
    sigaction(SIG_TEST, &sig, NULL);
 
    /* kernel needs to know our pid to be able to send us a signal ->
      * we use debugfs for this -> do not forget to mount the debugfs!
      */
    configfd = open("/sys/kernel/debug/signalconfpid", O_WRONLY);
    if(configfd < 0) {
        perror("open");
        return -1;
    }
    sprintf(buf, "%i", getpid());
    if (write(configfd, buf, strlen(buf) + 1) < 0) {
        perror("fwrite"); 
        return -1;
    }
 
    return 0;
}

 

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now