Linux Kernel Threads Tutorial: kthread_create, kthread_run and kthread_stop Explained-Free Linux Device Drivers Course

Linux Kernel Threads Tutorial: kthread_create, kthread_run and kthread_stop Explained
A free, hands-on Linux kernel development course lecture — updated for kernel 6.x
Difficulty: Intermediate
Kernel Version: 6.x
Reading Time: 12 min
← Previous Lecture Next Lecture →

This Linux kernel threads tutorial is the next lecture in our free Linux kernel programming course. If you have followed our earlier lessons on kernel timers and workqueues, you already know how the kernel schedules deferred work. Now it’s time to look at a more direct tool: the kernel thread, or “kthread” for short. By the end of this Linux kernel threads tutorial you will be able to create, run, and safely stop your own kernel threads on a modern 6.x kernel, and you will understand exactly when a kthread is the right tool compared to a workqueue or a timer.

Part of our free courses:
Free Embedded Systems Course Free Linux Development Course Free Linux Device Drivers Course Free Linux Kernel Development Course

What You Will Learn

  • What a kernel thread actually is, and how it differs from a user-space thread
  • The role of kthreadd, the parent of every kernel thread
  • How to create and start a kernel thread with kthread_create() and kthread_run()
  • How to stop a kernel thread cleanly using kthread_should_stop() and kthread_stop()
  • A complete, original, working kernel module example built for kernel 6.x
  • When to prefer a kthread over a workqueue or a timer callback
  • Common mistakes, debugging tips, and best practices

Prerequisites

Before starting this Linux kernel threads tutorial, you should be comfortable with:

  • Writing and loading a basic Linux kernel module (insmod / rmmod)
  • Our earlier lecture on Linux kernel timers (timer_setup, mod_timer, timer_delete_sync)
  • Basic C pointers and function pointers
  • A Linux VM or test machine running kernel 6.x, with kernel headers installed

What Exactly Is a Linux Kernel Thread?

A kernel thread is an independent execution context that runs entirely inside the kernel’s virtual address space, with kernel privilege, and has no associated user-space memory map. Unlike a regular process thread, a kthread never runs application code and never returns to user mode. It exists purely to run one kernel function, and once that function returns, the thread is gone.

Every kthread you create is, at the process-management level, spawned by a special ancestor thread called kthreadd, which itself is forked directly from PID 0 during boot. You can see this ancestry on any running Linux system:

$ ps -ef | grep kthreadd
root         2     0  0 Jan01 ?        00:00:00 [kthreadd]
$ ps -ef --ppid 2 | head
root         3     2  0 Jan01 ?        00:00:00 [rcu_gp]
root         4     2  0 Jan01 ?        00:00:00 [rcu_par_gp]
root         9     2  0 Jan01 ?        00:00:00 [kworker/0:0H]

Any process name shown in square brackets by ps is a kernel thread — it has no executable image, no user stack, and no open file descriptors in the usual sense.

Kernel Thread Lifecycle — Inline Diagram
kthread_create()
→
wake_up_process() / kthread_run()
→
Thread function loop
(checks kthread_should_stop())
→
kthread_stop()
thread exits

Creating a Kernel Thread: kthread_create() and kthread_run()

The kernel exposes two closely related APIs for spinning up a new kthread. kthread_create() only creates the thread structure and leaves it dormant; you must explicitly wake it with wake_up_process(). The convenience wrapper kthread_run() does both steps for you — create and wake — in a single call, which is what most modern driver code uses.

API Behavior Typical Use
kthread_create(fn, data, name) Creates thread in sleeping state, not yet runnable When you need to set CPU affinity or priority before starting
kthread_run(fn, data, name) Creates and immediately wakes the thread Most driver code — the common case
kthread_stop(task) Signals stop, wakes thread if sleeping, waits for exit Module unload / cleanup path

Original Kernel Thread Example (Kernel 6.x)

Below is a small, original character-driver-free example module we wrote specifically for this lecture. It starts a kthread on module load that logs a counter once a second, and stops it cleanly on module removal using the modern API — no deprecated calls, no busy-waiting.

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/sched.h>

static struct task_struct *ep_kthread;

static int ep_thread_fn(void *data)
{
    unsigned long counter = 0;

    pr_info("ep_kthread: started, pid=%d\n", current->pid);

    while (!kthread_should_stop()) {
        pr_info("ep_kthread: tick %lu\n", counter++);
        /* set_current_state() + schedule_timeout() gives a
         * cleanly interruptible sleep that kthread_stop()
         * can wake up immediately */
        set_current_state(TASK_INTERRUPTIBLE);
        schedule_timeout(HZ);
    }

    pr_info("ep_kthread: stopping, exiting cleanly\n");
    return 0;
}

static int __init ep_kthread_init(void)
{
    ep_kthread = kthread_run(ep_thread_fn, NULL, "ep_kthread_demo");
    if (IS_ERR(ep_kthread)) {
        pr_err("ep_kthread: failed to create thread\n");
        return PTR_ERR(ep_kthread);
    }
    return 0;
}

static void __exit ep_kthread_exit(void)
{
    kthread_stop(ep_kthread);
}

module_init(ep_kthread_init);
module_exit(ep_kthread_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("EmbeddedPathashala original kthread demo - kernel 6.x");

Two details matter here for correctness on kernel 6.x. First, kthread_should_stop() is checked at the top of the loop, not buried inside a blocking call, so the thread always gets a chance to exit. Second, we use set_current_state(TASK_INTERRUPTIBLE) paired with schedule_timeout() rather than msleep(), because kthread_stop() wakes the target task, and an interruptible sleep responds to that wake-up instantly instead of finishing out a fixed delay.

Stopping a Kernel Thread Safely

The single most common bug in kthread-based drivers is a thread that never stops, hanging rmmod forever. kthread_stop() solves this by doing three things atomically from the caller’s side: it sets an internal stop flag, wakes the target thread if it is sleeping, and then blocks until the thread’s function has actually returned. Your thread function is responsible for polling kthread_should_stop() and returning promptly when it becomes true — the kernel will not force-kill a kthread for you.

Kernel Threads vs. Workqueues vs. Timers

Mechanism Runs In Can Sleep? Best For
Kernel threadOwn dedicated task contextYesLong-running, self-scheduled background work
WorkqueueShared or dedicated kworker contextYesOne-shot or occasional deferred work items
Kernel timerSoftirq / interrupt-like contextNoPrecise, short, non-blocking deadline callbacks

If your earlier reading of this course’s kernel timers lecture left you wondering why the timer callback there could not simply sleep, this table is the answer: a kthread is the tool you reach for exactly when the work needs to block, loop, or run indefinitely.

Real-World Use Cases

  • Polling a hardware status register at a fixed cadence when no interrupt line is available
  • Storage and networking subsystems that need a dedicated flusher or garbage-collector thread
  • Watchdog-style monitoring threads inside a driver subsystem
  • Background maintenance tasks such as RCU’s own rcu_gp kthreads

Common Mistakes and Troubleshooting

  • Forgetting to check kthread_should_stop(): the module hangs on unload because kthread_stop() waits forever for the thread to return.
  • Using msleep() instead of an interruptible sleep: shutdown becomes sluggish since the thread only notices the stop request after its sleep interval ends.
  • Not checking IS_ERR() on the return value: kthread_run() and kthread_create() return an error pointer on failure, not NULL.
  • Calling kthread_stop() on an already-exited thread pointer: always guard your exit path so cleanup only runs once.

Best Practices

  • Always pair a poll loop with kthread_should_stop() at the top of the iteration.
  • Prefer schedule_timeout() with TASK_INTERRUPTIBLE over fixed-delay sleep functions inside a kthread loop.
  • Give your kthread a descriptive name — it shows up directly in ps and /proc, which is invaluable for debugging.
  • Keep the thread function focused on one job; use a workqueue for secondary one-off tasks it triggers.

Performance and Security Considerations

Each kthread consumes a full kernel stack, so spawning large numbers of them for fine-grained parallel work is generally wasteful — a shared workqueue is more memory-efficient in that scenario. From a security standpoint, remember that a kthread runs with full kernel privilege and no seccomp-style sandboxing, so any data it consumes from user space must still go through the same validation your ioctl or sysfs handlers apply.

Summary / Key Takeaways

  • A kernel thread is a dedicated, sleep-capable execution context living entirely in kernel space.
  • Use kthread_run() to create and start a thread in one call; use kthread_create() when you need to configure it before starting.
  • Always check kthread_should_stop() in your loop and let kthread_stop() handle a clean, blocking shutdown.
  • Choose kthreads over timers and workqueues specifically when the work must sleep or run indefinitely.

Conclusion

This Linux kernel threads tutorial gave you a complete, modern-kernel-safe pattern for creating and tearing down kernel threads: the API calls, an original working example, and the judgment calls that separate a kthread from a workqueue or a timer. As with the rest of this free Linux kernel development course, the goal is not just to compile a module, but to understand why each API call exists and what breaks if you skip it. In the next lecture we will build on this thread with a producer/consumer kthread pair to show real synchronization in action.

Frequently Asked Questions

Q1. What is the difference between a kernel thread and a user-space thread?
A kernel thread runs only in kernel space, has no user-mode memory mapping, and never executes application code, while a user-space thread runs within a process and can enter the kernel only through system calls.

Q2. Do I need to call kthread_stop() even if my thread function already returned?
Yes — kthread_stop() is what actually reaps the thread and returns its exit value; skipping it can leave dangling task references.

Q3. Can a kernel thread sleep?
Yes, and that is one of its biggest advantages over a timer callback, which runs in a context that cannot sleep.

Q4. What happens if I call kthread_stop() on a thread that never checks kthread_should_stop()?
The caller of kthread_stop() blocks indefinitely, and in practice this hangs rmmod.

Q5. Is kthread_create() ever preferred over kthread_run()?
Yes, when you need to set CPU affinity, scheduling policy, or priority on the task_struct before the thread starts executing.

Q6. Are kthreads visible in ps output?
Yes, they appear with their name in square brackets, for example [ep_kthread_demo].

Q7. Is this API different on older kernels?
The core kthread_create() / kthread_run() / kthread_stop() trio has been stable for a long time; this lecture reflects current best practice for kernel 6.x.

Continue this free Linux kernel development course with our next lecture.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *