文章目录
背景
在计算机科学中,mutex 是 “mutual exclusion”(互斥)的缩写,它是一种同步机制,用于防止多个线程或进程同时访问共享资源,从而避免出现数据不一致或冲突等问题。
本文展示mutex(互斥锁)的两种实现方式:静态定义(DEFINE_MUTEX)和动态分配(mutex_init)。
互斥锁mutex的一些基本特点、约束和限制
基本特点:
- 互斥性:同一时间只能有一个持有者(进程 / 线程)。
- 睡眠等待:获取不到锁时,进程会进入睡眠状态(TASK_INTERRUPTIBLE 或 TASK_UNINTERRUPTIBLE),不会消耗 CPU 资源。
- 所有权:锁的持有者必须是获取它的进程,且只能由持有者释放(防止误释放)。
- 非递归:同一进程不能对已持有的 mutex 再次加锁(否则会导致死锁)。
主要限制(重点关注中断上下文):
- 不能在中断上下文使用
中断上下文(如中断处理函数、软中断、tasklet 等)中不能使用 mutex,因为获取 mutex 时可能会导致进程睡眠,而中断上下文不允许睡眠(没有可调度的进程实体),强行使用会引发内核崩溃。
若中断处理函数中尝试获取一个已被持有(如被进程上下文持有)的 mutex,会导致死锁(进程等待中断处理完成,中断等待进程释放锁)。
不能在原子上下文使用 - 原子上下文(如持有 spinlock 时、禁止抢占的代码段)中也不能使用 mutex,因为原子上下文同样不允许睡眠。
- 持有时间不宜过长
由于 mutex 会导致等待进程睡眠,若持有锁的时间过长,会降低系统响应性,适合保护短时间的临界区。长时间持有锁应考虑其他机制(如信号量)。 - 初始化与销毁限制
静态定义的 mutex 需用 DEFINE_MUTEX(name) 初始化。
动态分配的 mutex 需用 mutex_init(&mutex) 初始化,且必须在使用前完成。
销毁 mutex 前必须确保它已被释放,且没有进程在等待它。
互斥锁mutex与 自旋锁spinlock 的对比
| 特性 | mutex | spinlock |
|---|---|---|
| 等待方式 | 睡眠(不占用 CPU) | 忙等(占用 CPU) |
| 适用场景 | 临界区执行时间较长 | 临界区执行时间极短 |
| 中断上下文 | 禁止使用 | 可使用(需配合关中断) |
| 递归加锁 | 不支持 | 不支持(特殊变种除外) |
简单来说,mutex 是用户态互斥锁在 kernel 中的对应实现,但受内核上下文特性限制,其使用场景比用户态更严格,尤其是绝对禁止在中断上下文使用。
内核KO
C:
静态定义核心几点:
static DEFINE_MUTEX(static_mutex);//初始化
mutex_lock_interruptible(&static_mutex)//上锁
mutex_unlock(&static_mutex);//解锁
动态定义核心几点:
dynamic_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
mutex_init(dynamic_mutex); //初始化
mutex_lock_interruptible(dynamic_mutex) //上锁
mutex_unlock(dynamic_mutex); //解锁
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("beiming");
MODULE_DESCRIPTION("A mutex example module showing initialization, usage, and cleanup");
MODULE_VERSION("0.1");
// 静态定义的mutex
static DEFINE_MUTEX(static_mutex);
// 动态分配的mutex
static struct mutex *dynamic_mutex;
// 共享资源
static int shared_resource = 0;
// 内核线程函数
static struct task_struct *thread1;
static struct task_struct *thread2;
// 使用静态mutex的线程工作函数
static int static_mutex_thread(void *data)
{
int thread_id = *(int *)data;
int i;
for (i = 0; i < 3

最低0.47元/天 解锁文章
4511

被折叠的 条评论
为什么被折叠?



