Search

Kernel Thread Creation : 1

The Linux way of handling threads is unique when compared to the traditional approach. Generally a thread and a process are treated in different ways, but in case of linux thread is also just another process and is handled in the same fashion as any other process.
Let us take write a small module to create a kernel thread and try to understand the various functions involved in the same.

To work with threads you would need the header file linux/kthread.h
A thread is created by the call to the function
struct task_struct *kthread_create(int (*function)(void *data),
                                   void *data,
                                   const char name[],
                                   ...)

The function takes the following arguments
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 recognised in the kernel.

A thread created using the above call does not run but only gets created. To run the thread we need to call the function "wake_up_process" passing the thread id that is returned by "kthread_create".

When the wake_up_process is called the function passed to kthread_create gets executed.

To stop a thread that is running we need to call the kthread_stop(struct task_struct *threadid) where threadid is the same that is returned by the kthread_create call.

To understand the working of these system calls better let us create a module and create a kernel thread in it.

We need the following header files

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

#include <linux/kthread.h>  // for threads
#include <linux/sched.h>  // for task_struct
#include <linux/time.h>   // for using jiffies 
#include <linux/timer.h>




Let us spawn a kernel thread as soon as the module gets inserted into the kernel, so we will have to add the kernel creation part in the init function.

static struct task_struct *thread1;

int thread_init (void) {
   
    char our_thread[8]="thread1";
    printk(KERN_INFO "in init");
    thread1 = kthread_create(thread_fn,NULL,our_thread);
    if((thread1))
        {
        printk(KERN_INFO "in if");
        wake_up_process(thread1);
        }

    return 0;
}
In the call to kthread_create we have passed the following arguments

thread_fn : Which is the function that will be run as the thread.
NULL: As we are not passing any data to the function we have kept this NULL.
name: The process will be named "thread1" in the list of processes .

Now we need to implement the function "thread_fn" . The following functions prints a statement and waits for one minute before exiting. (If the syntax of waiting and jiffies is not clear right now, we will cover that soon ) .
The wait is just to give us enough time to look at the thread running.

int thread_fn() {

unsigned long j0,j1;
int delay = 60*HZ;
j0 = jiffies;
j1 = j0 + delay;

printk(KERN_INFO "In thread1");

while (time_before(jiffies, j1))
        schedule();

return 0;
}


To kill a running thread we can use the system call kthread_stop(struct task_struct *threadid). Note that in case the thread does not exist this call would end up in segmentation fault.




Putting all the above code together the complete code is as follows


#############################################################

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>  // for threads
#include <linux/sched.h>  // for task_struct
#include <linux/time.h>   // for using jiffies 
#include <linux/timer.h>




static struct task_struct *thread1;


int thread_fn() {

unsigned long j0,j1;
int delay = 60*HZ;

printk(KERN_INFO "In thread1");
j0 = jiffies;
j1 = j0 + delay;

while (time_before(jiffies, j1))
        schedule();

return 0;
}

int thread_init (void) {
   
    char  our_thread[8]="thread1";
    printk(KERN_INFO "in init");
    thread1 = kthread_create(thread_fn,NULL,our_thread);
    if((thread1))
        {
        printk(KERN_INFO "in if");
        wake_up_process(thread1);
        }

    return 0;
}



void thread_cleanup(void) {
   

}
MODULE_LICENSE("GPL");   
module_init(thread_init);
module_exit(thread_cleanup);

#############################################################


The makefile need to compile the code is, assuming the above code is saved as threads.c

#############################################################

ifneq ($(KERNELRELEASE),)
   obj-m := threads.o
else

KERNELDIR ?= /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endif
#############################################################

Now run the following commands

$ make
$ sudo insmod threads.ko
If this happens with out any errors, run the following command to see the thread running.
$ ps -ef | grep thread
root      2589     2 99 12:43 ?        00:00:19 [thread1]

The timer in previous to last column shows from how long the thread has been running.

To remove the module run the command

$ sudo rmmod threads
If you try to remove thread before a minute it will keep waiting until the thread exits.

Note: As of now we have left the cleanup function blank as the thread exits by itself at the end of a minute. We will look into more complicated threads that will need explicit call to the "kthread_stop"


Follow by Email