How to stop Linux kernel threads on rmmod?

41,305

Solution 1

You should use only one of kthread_create() or kthread_run():

/**
 * kthread_run - create and wake a thread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: Convenient wrapper for kthread_create() followed by
 * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
 */
#define kthread_run(threadfn, data, namefmt, ...)                      \
({                                                                     \
    struct task_struct *__k                                            \
            = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
    if (!IS_ERR(__k))                                                  \
            wake_up_process(__k);                                      \
    __k;                                                               \
})

So you're creating two threads and leaking one of them:

task = kthread_create(&thread_function,(void*) &data,"pradeep");
task = kthread_run(&thread_function,(void*) &data,"pradeep");

Furthermore, your thread function might be missing some details:

/**
 * kthread_create - create a kthread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: This helper function creates and names a kernel
 * thread.  The thread will be stopped: use wake_up_process() to start
 * it.  See also kthread_run().
 *
 * When woken, the thread will run @threadfn() with @data as its
 * argument. @threadfn() can either call do_exit() directly if it is a
 * standalone thread for which noone will call kthread_stop(), or
 * return when 'kthread_should_stop()' is true (which means
 * kthread_stop() has been called).  The return value should be zero
 * or a negative error number; it will be passed to kthread_stop().
 *
 * Returns a task_struct or ERR_PTR(-ENOMEM).
 */

I think the two choices for terminating a thread are:

  1. Call do_exit() when you're done.
  2. Return a value when another thread calls kthread_stop().

Hopefully after fixing these two small problems, you'll have a functional thread creator / reaper.

Solution 2

I hope the below program resolves your problem.... thumbs up :-)

`#include<linux/init.h>
 #include<linux/module.h>
 #include<linux/kernel.h>
 #include<linux/kthread.h>
 #include<linux/sched.h>`

struct task_struct *task;
int data;
int ret;
int thread_function(void *data)
{
  int var;
 var = 10;
     printk(KERN_INFO "IN THREAD FUNCTION");
     while(!kthread_should_stop()){
             schedule();
             }
     /*do_exit(1);*/
  return var;

}

static int kernel_init(void)
{
   data = 20;
   printk(KERN_INFO"--------------------------------------------");
   /*task = kthread_create(&thread_function,(void *)data,"pradeep");*/
   task = kthread_run(&thread_function,(void *)data,"pradeep");
   printk(KERN_INFO"Kernel Thread : %s\n",task->comm);
   return 0;
}

static void kernel_exit(void)
{
   kthread_stop(task);
}

module_init(kernel_init);
module_exit(kernel_exit);
MODULE_AUTHOR("SHRQ");
MODULE_LICENSE("GPL");
Share:
41,305

Related videos on Youtube

pradeepchhetri
Author by

pradeepchhetri

Updated on May 14, 2020

Comments

  • pradeepchhetri
    pradeepchhetri almost 4 years

    I wrote the following code to create a kernel thread:

    #include<linux/init.h>
    #include<linux/module.h>
    #include<linux/kernel.h>
    #include<linux/kthread.h>
    #include<linux/sched.h>
    
    struct task_struct *task;
    int data;
    int ret;
    int thread_function(void *data)
    {
        int var;
        var = 10;
        return var;
    }
    
    static int kernel_init(void)
    {
        data = 20;
        printk(KERN_INFO"--------------------------------------------");
        task = kthread_create(&thread_function,(void *)data,"pradeep");
        task = kthread_run(&thread_function,(void *)data,"pradeep");
        printk(KERN_INFO"Kernel Thread : %s\n",task->comm);
        return 0;
    }
    
    static void kernel_exit(void)
    {
        ret = kthread_stop(task);
    }
    
    module_init(kernel_init);
    module_exit(kernel_exit);
    

    On giving the insmod command, I am able to create a kernel thread named "pradeep" and I can see the new thread using the ps -ef command as follows

    root      6071     2  0 10:21 ?        00:00:00 [pradeep]
    

    and its parent is kthreadd whose PID is 2. But I am not able to stop this thread on giving rmmod command. It is giving the following output:

    ERROR: Removing 'pradeep': Device or resource busy.
    

    Can somebody please tell me how to kill this thread?

  • pradeepchhetri
    pradeepchhetri about 13 years
    I corrected the first problem but i didn't understand the second prbblem. Can you please explain me the second one in detail.
  • sarnold
    sarnold about 13 years
    @pradeepchhetri, did you get your problem solved? I'm sorry I missed this for almost a week. About terminating the thread, it looks like you have only two choices: calling do_exit() in your thread function (rather than falling off the end of the function or trying to return a value); or polling kthread_should_stop() periodically: when it returns true, then you need to return 0 (for success) or return one of the error codes for a failure.
  • Jayzcode
    Jayzcode about 7 years
    task = kthread_create(&thread_function,(void *)data,"pradeep"); wake_up_process(task) OR task = kthread_run(&thread_function,(void *)data,"pradeep");
  • Abhishek Sagar
    Abhishek Sagar about 7 years
    Hi, i am writing a multi threading intensive driver in kernel. Since, printk doesnt work with kernel threads , how can i log the info by kernel threads so as to debug easier ?
  • sarnold
    sarnold about 7 years
    @AbhishekSagar, I had not heard that printk() doesn't work from kernel threads -- are you sure about that? If so, you'd be best served to ask a new question, ideally with a simple fifteen-line kernel module that demonstrates the issue. Thanks.
  • Abhishek Sagar
    Abhishek Sagar about 7 years
    @sarnold Hi, printk do work with kernel threads, I was doing something wrong.