I am developing Linux kernel module which is communicating with my user-space C application. In this module, I am creating a thread. Besides, I need to know the pid of the user space process, so I am using pid_task(find_vpid(pid), PIDTYPE_PID) function.
This is my module where I am facing the problem :
#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/signal.h> //find_task_by_pid_type
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include<linux/slab.h>
#include <linux/input.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/random.h>
#include <linux/kthread.h>
#define SIG_TEST 44 // we choose 44 as our signal number (real-time signals are in the range of 33 to 64)
#define BTN_FILE_PATH "/dev/input/event0"
char *str = BTN_FILE_PATH;
int file;
struct file *f; // keyboard driver
// prototypage des fonctions read_in_thread & read_pid
int read_in_thread(void *data);
static ssize_t read_pid(struct file *pfile, char __user *buffer, size_t length, loff_t *offset);
static ssize_t write_pid(struct file *pfile, const char __user *buffer,
size_t length, loff_t *offset)
{
return 0;
}
struct read_args {
struct file *pfile;
const char __user *buffer;
size_t length;
loff_t *offset;
};
static ssize_t read_pid(struct file *pfile, char __user *buffer, size_t length, loff_t *offset)
{
// création de la structure des arguments
struct read_args args ;
args.pfile = pfile;
args.buffer = buffer;
args.length = length;
args.offset = offset;
struct task_struct *thread1;
char our_thread[20];
unsigned int rand;
get_random_bytes(&rand, sizeof(rand));
rand = rand % 250;
sprintf(our_thread, "thread%u", rand);
if(thread1==NULL)
{
thread1 = kthread_create(read_in_thread,&args,our_thread);
if((thread1))
{
printk(KERN_INFO "Thread is created\n");
printk("thread name %s\n", our_thread);
// lancement du thread
wake_up_process(thread1);
printk(KERN_INFO "Thread is awake\n");
}
}
else
printk("\nTHREAD1 IS NOT NULL!!! CAN NOT CREATE THREAD!!!\n");
return 0;
}
int read_in_thread(void *data) {
/************************** récupération des arguments *******************/
struct read_args *const args = data;
/*************************** corps de la fonction ***********************/
// init des variables
char mybuf[10];
enum { MAX_BUF_SIZE = 4096 };
size_t buf_size = 0;
char *buf = NULL;
ssize_t total = 0;
ssize_t rc = 0;
struct task_struct *t;
struct input_event ev[64];
int yalv;
int ret;
struct siginfo info;
int pid =0;
size_t amount = sizeof(ev);
// récupération de l'ID du processus appelant
/* read the value from user space */
if(args->length > 10)
return -EINVAL;
copy_from_user(mybuf, args->buffer, args->length);
sscanf(mybuf, "%d", &pid);
printk("pid = %d\n", pid);
// 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 = 260; //real time signals may have 32 bits of data.
rcu_read_lock();
t = pid_task(find_vpid(pid), PIDTYPE_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();
// lecture blocquante
rc = kernel_read(f, ev, amount, &f->f_pos);
// récupération de l'événement
if (rc > 0) {
for (yalv = 0; yalv < (int) (rc / sizeof(struct input_event)); yalv++) {
if (ev[yalv].type == EV_KEY) {
if (ev[yalv].value == 0)
//eval_keycode(ev[yalv].code);
info.si_int = ev[yalv].code;
// envoie du signal vers le processus appelant avec les événements lu
ret = send_sig_info(SIG_TEST, &info, t); //send the signal
printk("signal was send\n");
if (ret < 0) {
printk("error sending signal\n");
kfree(buf);
return ret;
}
}
}
if (rc < amount) {
/* Didn't read the full amount, so terminate early. */
rc = 0;
}
}
/* Free temporary buffer. */
kfree(buf);
return 0;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.write = write_pid,
.read = read_pid,
//.open = open_pid,
};
static int __init signalexample_module_init(void)
{
printk(KERN_INFO "Initializing LKM");
register_chrdev(240, "mod", &my_fops);
file = debugfs_create_file("signalconfpid", 0200, NULL, NULL, &my_fops);
f = filp_open(str, O_RDONLY , 0);
return 0;
}
static void __exit signalexample_module_exit(void)
{
unregister_chrdev(240, "mod");
debugfs_remove(file);
}
module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
When I run my user-space program after inserting this module, it seems for the first time to work without a problem : it prints on the console :
Thread is created
thread name thread91
Thread is awake
pid = 323
But after I exit and when I try to re-execute my user space code again it shows to me :
pid = 0
No such pid
I want to know why it's not working in the right way when I execute my application for multiple times ? what's wrong here ? I need some help please. Thank you.
For anyone who is looking for a solution for this problem, after some researches I found that using copy_from_user
function must be used out of the thread function. So, I move it inside read_pid
function in my code and declared the variables which it used as global variables and I am able now to usually receive the correct PID of my user space application.