Monthly Archives: May 2015

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 >>

www.pdf24.org    Send article as PDF   

Water Level Indicator

This 4th article in the series of “Do It Yourself: Electronics”, takes you through using a bipolar junction transistor (BJT), as an electronic switch.

<< Previous Article

Pugs came out of the “Electronics Fundamentals” class, all loaded with internal details of a transistor. He was lost in his own world, when he crossed ways with Surya coming out of his class. Surya called Pugs, without any response. So, he came close and shook Pugs, “Hey Pugs! Where are you?”

Pugs, as if he woke up from deep sleep, “Hey! What happened? Where are you going?”

“Where were you lost? Whom were you remembering? Shall I call Simi?”

“Hey! Shut up yaar. Where did she come in between? I was thinking of how to use the transistors in a practical way”, replied Pugs showing anger.

“Okay. Okay. Cool down. I was just joking. So, today your class was about transistors.”

“Yes.”

“Last time when you went to buy some components, I asked you to get four BC546 transistors, right?”

“Yes. I got them.”

“So now, I think is the time to experiment with them, to bring you back from the lost world.”

“O Great! But you know what, if I remember correct, the shopkeeper didn’t have BC546, and so he gave some other number, saying that is equivalent.”

“Which number?”

“Not really sure.”

“No probs. Let’s go to your room and check it out.”

Both Surya and Pugs walks down to Pugs’ room.

Pugs took out the transistors, trying to check the number written on them.

“Looks like BC548. Can you check, Surya?”

“Yes it is BC548. That’s fine. In fact, BC546 & BC547 are same as BC548, except that they have higher break down voltages. Moreover, there are other variants as well, like BC549 – a low noise variant, BC550 – with both low noise and higher break down voltage.”

“I don’t understand your all these Greek-Latin – just tell me if what I got is okay.”

“Ya ya that’s fine. It is also NPN like the others.”

“Yes, that I understand – meaning there is a very thin layer with concentrated holes sandwiched between two layers with concentrated electrons, and so the electrons are the majority carriers in these kinds.”

“O! That’s great – you know quite a bit about them. Hmmm! I see the effect of the class”, said Surya staring at Pugs.

Interrupting Surya’s stare, Pugs said, “Ignore that, and tell me then, do we also have similar PNP transistors?”

“Yes. There is a similar series BC556 to BC560 for PNP transistors.”

“Hmmm! So now, what are we planning to do with these four BC548’s.”

“Use them as electronic switches for water level indication.”

And then goes the demonstration by Surya:

“Hey Surya! You have put the power line into the water. Isn’t that dangerous?”

“It is just 5 volts, Pugs. And more than that the current would be in micro amps, as it is the input to the base of the transistors.”

“I see. And that can be ignored – too small to observe in this noisy world.”

“With water, yes. However, with hazardous liquids like petrol, even that may not be okay.”

Next Article >>

www.pdf24.org    Send article as PDF