world leader in high performance signal processing
Trace: » threads

Kernel Threads

The kernel often needs to establish processes that sleep or wait for events to occur. It can use a lightweight process or thread for this task.

A kernel thread is very similar to a user process or thread in that it is a schedulable entity. This means that it has its own task control block and it can sleep while waiting for system events to be routed to it.

The only difference between a kernel thread and a user thread is the fact that the kernel thread has no user task memory mapping. Like other user processes it shares the kernel address space but the thread operates only in kernel space with kernel privilages.

This also means that when activating a kernel thread a lot of the overhead (cache , tlb etc) involved with switching a process's memory map is avoided.

Many kernel subsystems are managed by kernel threads. All the tasks in the [ ] braces in the example shown are, in fact, kernel threads.

ps ax
    1 ?        S      0:03 init [5]
    2 ?        SN     0:00 [ksoftirqd/0]
    3 ?        S<     0:01 [events/0]
    4 ?        S<     0:00 [khelper]
    5 ?        S<     0:00 [netlink/0]
    6 ?        S<     0:02 [kblockd/0]
   32 ?        S      0:00 [kapmd]
   37 ?        S<     0:00 [aio/0]
   36 ?        S      0:08 [kswapd0]

Using Kernel Threads

This is quite simple, you specify the function to be used as a thread an optional data item (used as an argument for the thread), and the thread creation flags. Normally a fixed set of these flags are used for a “normal” kernel thread.

A thread is normally designed as a continous loop that calls some wait or scheduling function to stop it consuming 100% of the CPU.

The example thread also uses a completion mechanism to telling the process that created it that the thread has been established and is ready for business.

The thread must manage its own signals and also remove any unneeded memory mapping information.

NOTE If the thread is part of a device driver and also a module it will, by default, inherit the user memory space of the user process that called insmod. This user space mapping should be removed.

// simple thread code
// not you need to add the loop task and the yield function
static int mythread(void * data)
       struct completion *comp = (struct completion *)data;
       // set up the thread
        daemonize("mythread");  // remove any user space mem maps and
                                // signal handlers
        allow_signal(SIGKILL);  // allow a kill signal
       // notify ready for action
       do  {
             // loop task to process data
             wait_event_interruptible(...)// yield process
       } while (!signal_pending(current));
       return 0;
// simple thread generation code
static int generate_thread (void)
        pid_t pid;
        pid = kernel_thread(mythread,  // thread function
                      &ready,     // data argument
                      CLONE_FS | CLONE_SIGHAND // flags

Starting a Kernel Thread

One of the first things a booting kernel does is start a kernel thread to complete the boot process.

static int init(void * unused);
static void rest_init(void)
                      NULL, CLONE_FS | CLONE_SIGHAND);

This “init” thread completes the boot process and then passes control to a user task. Infact the “init” thread becomes the “init” user process.