Kernel Thread Creation

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.hA 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/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 stop 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. The function kthread_stop does not terminate the thread but waits for the thread to terminate itself.

In our clean up function we will call kthread_stop and let the thread exit itself.

void thread_cleanup(void) { int ret; ret = kthread_stop(thread1); if(!ret) printk(KERN_INFO "Thread stopped"); }

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) { int ret; ret = kthread_stop(thread1); if(!ret) printk(KERN_INFO "Thread stopped"); } 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. But make sure you wait for a whole minute before running the command, because te

$ sudo rmmod threads

If you try to remove thread before a minute it will keep waiting until the thread exits which happens only at the end of a minute.


http://tuxthink.blogspot.com/2011/02/kernel-thread-creation-1.html

你可能感兴趣的:(thread,kernel)