【代码模版】Linux内核mutex用法?(mutex_init、mutex_lock_interruptible、mutex_unlock)

背景

在计算机科学中,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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值