Tag Archives: Kernel Threads

Kernel Threads Continued

<< Previous Article

In the previous article, we learned the basics of kernel threads such as creating the thread, running the thread and so on. In this article, we will dive a bit more into the kernel threads, where we will see the things such as stopping the thread, signalling the thread and so. So, let’s begin…

Continuing with the previous article, we were observing a crash while removing the kernel module with rmmod, So, are you able to find the reason for the crash? If yes, that’s very well done. The reason for the crash wasss … Let us first cover this article and hopefully, as a part of that, you by yourself would be able to discover the reason.

Stopping the Kernel Thread

If you are familiar with the pthreads in user space, you might have come across the call pthread_cancel(). With this call, one thread can send the cancellation request to the other. Pretty similar to this, there exists a call called kthread_stop() in kernel space. Below is the prototype for the same:

#include <linux/kthread.h>
int kthread_stop(struct task_struct *k);

Parameters:
k – pointer to the task structure of the thread to be stopped

Returns:  The result of the function executed by the thread, -EINTR, if wake_up_process() was never called.

Below is the code snippet which uses kthread_stop():

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/delay.h>

static struct task_struct *thread_st;
// Function executed by kernel thread
static int thread_fn(void *unused)
{
    while (1)
    {
        printk(KERN_INFO "Thread Running\n");
        ssleep(5);
    }
    printk(KERN_INFO "Thread Stopping\n");
    do_exit(0);
    return 0;
}
// Module Initialization
static int __init init_thread(void)
{
    printk(KERN_INFO "Creating Thread\n");
    //Create the kernel thread with name 'mythread'
    thread_st = kthread_run(thread_fn, NULL, "mythread");
    if (thread_st)
        printk(KERN_INFO "Thread Created successfully\n");
    else
        printk(KERN_ERR "Thread creation failed\n");
    return 0;
}
// Module Exit
static void __exit cleanup_thread(void)
{
   printk(KERN_INFO "Cleaning Up\n");
   if (thread_st)
   {
       kthread_stop(thread_st);
       printk(KERN_INFO "Thread stopped");
   }
}
MODULE_LICENSE("GPL");
module_init(init_thread);
module_exit(cleanup_thread);

Compile the code and insert the module with insmod. Now, try removing the module with rmmod. What do you see? Dude … where is my command prompt? rmmod seems to have got stuck..”. Relax guys!  I forgot to mention that kthread_stop(), is indeed a blocking call. It waits for the thread to exit and since our thread is in while(1), so hopefully, it will never exit and unfortunately, our rmmod will never come out. So, what does this mean? What we can infer from this, is that the kthread_stop() is just the signal, not the command. Calling kthread_stop() doesn’t gives you a license to kill/stop the thread, instead it just sets the flag in the task_struct() of the thread and waits for the thread to exit. It’s totally upto the thread to decide, when it would like to exit.  So, why is such a thing? Well, just think of the scenario where kernel thread has allocated a memory and would free it up once it exits. Had it been allowed to be killed in middle, thread would never be able to free up the memory. This, in turn would result in memory leak. This was the one of the simplest scenarios, which I could think of. Coming back to our problem, how do we get back the command prompt? Let’s try one more thing. In the user space, you might have used the kill  command to send the signal to the process. And one of the most powerful signal which process can’t mask is SIGKILL. So, lets use the same on the kernel thread as well. Find the id of the running kernel thread with ps command and then, use the following command:

kill -9 <thread_id>

So, what’s the result? Dude … this thread is invincible!. True, by default, kernel thread ignores all the signals. The reason behind this is same as explained above. Kernel thread has a full control over when can it be killed. So, the only way to get out of this problem is to kill the problem, that means, reboot the system. This program has a bug, so read on to fix this bug.

So, now the question is, how to let the kernel thread know that, somebody is willing to stop it. For this, there is a call called kthread_should_stop(). This function returns non-zero value, if there is any outstanding ‘stop’ request. Thread should invoke this call periodically and if it returns true, it should do the required clean up and exit. Below is the code snippet using this mechanism:

static struct task_struct *thread_st;
// Function executed by kernel thread
static int thread_fn(void *unused)
{
    while (!kthread_should_stop())
    {
        printk(KERN_INFO "Thread Running\n");
        ssleep(5);
    }
    printk(KERN_INFO "Thread Stopping\n");
    do_exit(0);
    return 0;
}

Here, the thread periodically invokes kthread_should_stop() and exits, if this function returns a non-zero value. In exit_module() function, we call kthread_stop() function to notify the thread, as earlier.

Signalling the Kernel Thread

As we have already seen, by default, kernel thread ignores all the signals. So, how do we send the signal to the kernel thread, if at all it’s required in some scenarios? Again, we have some set of calls to support this. First call is allow_signal(). Below is the prototype for the same:

void allow_signal(int sig_num)

Parameters:
sig_num – signal number

Unlike user space, there are no asynchronous signal handlers in kernel threads. So, thread should periodically invoke signal_pending() call to check if there is any pending signal and should act accordingly. Below is the prototype for the same:

int signal_pending(task_struct *p)

Parameters:
p – pointer to the task structure of the current thread

Returns:  Non-zero value, if signal is pending

Below is the code snippet for handling the signals:

static struct task_struct *thread_st;
// Function executed by kernel thread
static int thread_fn(void *unused)
{
    // Allow the SIGKILL signal
    allow_signal(SIGKILL);
    while (!kthread_should_stop())
    {
        printk(KERN_INFO "Thread Running\n");
        ssleep(5);
        // Check if the signal is pending
        if (signal_pending(thread_st))
            break;
    }
    printk(KERN_INFO "Thread Stopping\n");
    do_exit(0);
    return 0;
}

Compile the code and insert the module with insmod. Now, find the thread id using ps and execute the below command:

kill -9 <thread_id>

With this, you will see that thread exits, once it detects the SIGKILL signal. Now, just try removing the module with rmmod. What do you get? rmmod comes out gracefully without blocking.

Conclusion

So, with this, I am done with kernel threads. Aah! I missed out one thing from the last article. Why was that crash in the code from the last article? As you might have observed, when I call kthread_stop() in the exit module, the thread terminates after kthread_should_stop() returns true, and we don’t see a crash. So, does it mean that kthread_stop() prevents crash? In a way yes, but we need to understand the fundamental reason behind the crash. As you know, like any other process, thread also requires a memory to execute. So, where does this memory come from? No points for guessing the right answer, its from the module memory. So, when you unload the module, that memory is freed up and its no longer valid.  So, our poor chap tries to access that and its destined to crash.

So, that’s about the kernel threads. In the next article, we will touch upon the concurrency management in the kernel. So, stay tuned …

Next Article >>

   Send article as PDF   

Kernel Threads

<< Previous Article

In the previous article, we learned to write a simple kernel module. This was needed to kick start our journey into the Kernel Internals, as all of the code we are going to discuss, has to be pushed into the kernel as module. In this article, we will discuss about the Kernel Threads. So, lets begin…

Understanding Threads

Threads, also known as light weight processes are the basic unit of CPU initialization. So, why do we call them as light weight processes? One of the reason is that the context switch between the threads takes much lesser time as compared to processes, which results from the fact that all the threads within the process share the same address space, so you don’t need to switch the address space. In the user space, threads are created using the POSIX APIs and are known as pthreads. Some of the advantages of the thread, is that since all the threads within the processes share the same address space, the communication between the threads is far easier and less time consuming as compared to processes. And usually is done through the global variables. This approach has one disadvantage though. It leads to several concurrency issues and require the synchronization mechanisms to handle the same.

Having said that, why do we require threads? Need for the multiple threads arises, when we need to achieve the parallelism within the process. To give you the simple example, while working on the word processor, if we enable the spell and grammar check, as we key in the words, you will see red/green lines appear, if we type something syntactically/grammatically incorrect. This can most probably be implemented as threads.

Kernel Threads

Now, what are kernel threads? They are same as user space threads in many aspects, but one of the biggest difference is that they exist in the kernel space and execute in a privileged mode and have full access to the kernel data structures. These are basically used to implement background tasks inside the kernel. The task can be handling of asynchronous events or waiting for an event to occur. Device drivers utilize the services of kernel threads to handle such tasks. For example, the ksoftirqd/0 thread is used to implement the Soft IRQs in kernel. The khubd kernel thread monitors the usb hubs and helps in configuring  usb devices during hot-plugging.

APIs for creating the Kernel thread

Below is the API for creating the thread:

#include <kthread.h>
kthread_create(int (*function)(void *data), void *data, const char name[], ...)

Parameters:
function – The function that the thread has to execute
data – The ‘data’ to be passed to the function
name – The name by which the process will be recognized in the kernel

Retuns: Pointer to a structure of type task_struct

Below is an example code which creates a kernel thread:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>

static struct task_struct *thread_st;
// Function executed by kernel thread
static int thread_fn(void *unused)
{
    while (1)
    {
        printk(KERN_INFO "Thread Running\n");
        ssleep(5);
    }
    printk(KERN_INFO "Thread Stopping\n");
    do_exit(0);
    return 0;
}
// Module Initialization
static int __init init_thread(void)
{
    printk(KERN_INFO "Creating Thread\n");
    //Create the kernel thread with name 'mythread'
    thread_st = kthread_create(thread_fn, NULL, "mythread");
    if (thread_st)
        printk("Thread Created successfully\n");
    else
        printk(KERN_INFO "Thread creation failed\n");
    return 0;
}
// Module Exit
static void __exit cleanup_thread(void)
{
    printk("Cleaning Up\n");
}

In the above code, thread is created in the init_thread(). Created thread executes the function thread_fn(). Compile the above code and insert the module with insmod. Below is the output, you get:

Thread Created successfully

That’s all we get as an output. Now, you might be wondering why is thread_fn() not executing? The reason for this is, when we create the thread with kthread_create(), it creates the thread in sleep state and thus nothing is executed. So, how do we wake up the thread. We have a API wake_up_process() for this. Below is modified code which uses this API.

// Module Initialization
static struct task_struct *thread_st;
{
    printk(KERN_INFO "Creating Thread\n");
    //Create the kernel thread with name 'mythread'
    thread_st = kthread_create(thread_fn, NULL, "mythread");
    if (thread_st)
    {
        printk("Thread Created successfully\n");
        wake_up_process(thread_st);
    }
    else
        printk(KERN_INFO "Thread creation failed\n");
    return 0;
}

As you might notice, wake_up_process() takes pointer to task_struct as an argument, which in turn is returned from kthread_create(). Below is the output:

Thread Created successfully
Thread Running
Thread Running
...

As seen, running a thread is a two step process – First create a thread and wake it up using wake_up_process(). However, kernel provides an API, which performs both these steps in one go as shown below:

#include <kthread.h>
kthread_run(int (*function)(void *data), void *data, const char name[], ...)

Parameters:
function – The function that the thread has to execute
data – The ‘data’ to be passed to the function
name – The name by which the process will be recognized in the kernel

Returns: Pointer to a structure of type task_struct

So, just replace the kthread_create() and wake_up_process() calls in above code with kthread_run and you will notice that thread starts running immediately.

Conclusion

So, now we are comfortable with creating the threads, let us remove the module with rmmod.  What do you get? Oops…isn’t it? To understand the reason for the crash, stay tuned to my next article on kernel threads. Till then, good bye.

Next Article >>

   Send article as PDF