Skip to main content

Command Palette

Search for a command to run...

Understanding `mutex_lock_killable()` in Linux Kernel Modules

Updated
4 min readView as Markdown
Understanding `mutex_lock_killable()` in Linux Kernel Modules

Synchronization is one of the most important concepts in Linux kernel development. When multiple kernel threads access a shared resource simultaneously, improper synchronization can lead to race conditions, inconsistent data, or even kernel crashes.

One of the synchronization primitives provided by the Linux kernel is mutex_lock_killable(). It behaves similarly to mutex_lock(), but allows a waiting task to return if interrupted by an appropriate fatal signal.

In this article, we'll explore the fundamentals of mutex_lock_killable() through a simple Linux Kernel Module.


Prerequisites

Before following this tutorial, you should be familiar with:

  • Linux Kernel Modules
  • C Programming
  • Kernel Threads
  • Basic Linux Commands
  • Synchronization Fundamentals

What is a Mutex?

A Mutex (Mutual Exclusion Lock) ensures that only one execution context can access a shared resource at a time.

Without synchronization:

  • Race conditions occur
  • Shared data becomes inconsistent
  • Kernel behavior becomes unpredictable

Using a mutex guarantees exclusive access to the critical section.


Why mutex_lock_killable()?

The Linux kernel provides multiple mutex APIs.

API Behavior
mutex_lock() Wait indefinitely until the lock becomes available
mutex_lock_interruptible() Can be interrupted by interruptible signals
mutex_lock_killable() Can return if interrupted by an appropriate fatal signal

In many driver scenarios, allowing a blocked task to terminate gracefully is preferable to waiting forever.


Demo Overview

The demonstration module creates two kernel threads.

  • Thread-1 acquires the mutex.
  • Thread-2 attempts to acquire the same mutex.
  • Since the mutex is already held, Thread-2 blocks.
  • After Thread-1 releases the mutex, Thread-2 continues execution.

This simple example illustrates how mutual exclusion works inside the Linux kernel.


Core Kernel APIs

The project uses several commonly used kernel APIs.

DEFINE_MUTEX(my_mutex);

mutex_lock_killable(&my_mutex);

mutex_unlock(&my_mutex);

kthread_run(...);

msleep(5000);

pr_info(...);

Each API plays a specific role:

  • DEFINE_MUTEX() creates a mutex.
  • mutex_lock_killable() acquires the mutex.
  • mutex_unlock() releases it.
  • kthread_run() creates kernel threads.
  • msleep() simulates work.
  • pr_info() prints kernel log messages.

Critical Section

A Critical Section is the portion of code that accesses shared resources.

Only one thread should execute this region at any given time.

In the demo:

  • Thread-1 enters the critical section.
  • Thread-2 waits.
  • After unlocking, Thread-2 proceeds.

This guarantees safe access to shared resources.


Building the Module

Compile the module using:

make

If Secure Boot is enabled, sign the kernel module before loading.

sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file \
sha256 \
~/kernel_keys/MOK.key \
~/kernel_keys/MOK.crt \
mutex_killable_demo.ko

Loading the Module

Insert the module:

sudo insmod mutex_killable_demo.ko

Monitor kernel logs:

sudo dmesg -wH

Verify the module:

lsmod | grep mutex_killable_demo

View running kernel threads:

ps -eLf | grep killable

Unload the module:

sudo rmmod mutex_killable_demo

Expected Execution

When the module runs, the output typically follows this sequence:

  1. Thread-1 starts.
  2. Thread-1 acquires the mutex.
  3. Thread-2 starts.
  4. Thread-2 blocks while waiting.
  5. Thread-1 releases the mutex.
  6. Thread-2 acquires the mutex.
  7. Thread-2 completes execution.
  8. Module unloads successfully.

Practical Use Cases

Understanding kernel synchronization is useful when developing:

  • Character Device Drivers
  • Platform Drivers
  • PCI Drivers
  • USB Drivers
  • Network Drivers
  • Filesystem Modules
  • Embedded Linux Systems
  • Linux Kernel Subsystems

Key Learning Outcomes

After completing this project, you should understand:

  • Linux kernel synchronization
  • Kernel threads
  • Mutex locking
  • Critical sections
  • Blocking synchronization
  • Kernel logging
  • Mutual exclusion
  • Safe shared resource access

Important Note

In this educational example, both workers are kernel threads. Since kernel threads typically do not receive user-space signals, the behavior of mutex_lock_killable() appears very similar to mutex_lock().

The primary advantage of mutex_lock_killable() becomes more apparent in kernel drivers where a user-space process blocks while waiting for a mutex and may receive a fatal signal.


Conclusion

Although the demo is intentionally simple, it introduces several core Linux kernel concepts that appear throughout driver development.

Understanding synchronization primitives like mutex_lock_killable() is an important step toward writing reliable kernel modules and avoiding race conditions in concurrent kernel code.

As you continue learning Linux kernel development, you can extend this project by experimenting with additional synchronization mechanisms such as semaphores, spinlocks, completions, wait queues, and reader-writer locks.


GitHub Repository

👉 GitHub Repository:
https://github.com/aj333git/linux_kernel_mutex_killable

Explore the complete source code, build files, and Linux kernel module implementation.