内核中的互斥锁的使用

在内核中结构体struct mutex的定义

// include/linux/mutex.h

/*
 * Simple, straightforward mutexes with strict semantics:
 *
 * - only one task can hold the mutex at a time
 * - only the owner can unlock the mutex
 * - multiple unlocks are not permitted
 * - recursive locking is not permitted
 * - a mutex object must be initialized via the API
 * - a mutex object must not be initialized via memset or copying
 * - task may not exit with mutex held
 * - memory areas where held locks reside must not be freed
 * - held mutexes must not be reinitialized
 * - mutexes may not be used in hardware or software interrupt
 *   contexts such as tasklets and timers
 *
 * These semantics are fully enforced when DEBUG_MUTEXES is
 * enabled. Furthermore, besides enforcing the above rules, the mutex
 * debugging code also implements a number of additional features
 * that make lock debugging easier and faster:
 *
 * - uses symbolic names of mutexes, whenever they are printed in debug output
 * - point-of-acquire tracking, symbolic lookup of function names
 * - list of all locks held in the system, printout of them
 * - owner tracking
 * - detects self-recursing locks and prints out all relevant info
 * - detects multi-task circular deadlocks and prints out all affected
 *   locks and tasks (and only those tasks)
 */
struct mutex {
	atomic_long_t		owner;
	spinlock_t		wait_lock;
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
	struct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
	struct list_head	wait_list;
#ifdef CONFIG_DEBUG_MUTEXES
	void			*magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map	dep_map;
#endif
};

竞争者从调度器的运行队列中删除,放入处于睡眠状态的等待链表(wait_list)中,然后内核调度并执行其他任务。当锁被释放时,等待队列中的等待者被唤醒,从wait_list中溢出,然后被重新调度。

相关函数

// 静态声明
DEFINE_MUTEX(struct mutex);

// 动态声明
struct mutex test_mutex;
mutex_init(&test_mutex);

// 获取互斥锁
void mutex_lock(struct mutex *lock);
int mutex_lock_interruptible(struct mutex *lock);
int mutex_lock_killable(struct mutex *lock);

// 解锁
void mutex_unlock(struct mutex *lock);

// 检查互斥锁是否已经被持有
int mutex_is_locked(struct mutex *lock);

// 尝试获取互斥锁,如果没有被锁定,则获取互斥锁
int mutex_trylock(struct mutex *lock);

与等待队列的可终端函数一样,建议使用mutex_lock_interruptible(),它使驱动可以被所有信号中断,mutex_lock_killable(),只有杀死进程的信号才能中断驱动程序,也就是说mutex_lock()不响应所有的信号,建议的使用组合为mutex_lock()+mutex_unlock_interruptible()

从内核函数说明来看,需要严格遵守一些规则。

  • 一次只能有一个任务持有互斥锁
  • 只能有互斥锁的持有者才能解锁
  • 不允许多次解锁
  • 不允许递归锁定
  • 互斥对象必须通过 API 初始化
  • 互斥对象不得通过memset或复制进行初始化
  • 任务可能不会在持有互斥锁的情况下退出,由于互斥锁保持锁定,竞争者可能永远等待(睡眠)
  • 不得释放持有锁所在的内存区域
  • 不得重新初始化持有的互斥锁
  • 互斥锁不能用于硬件或软件中断
  • 由于互斥锁涉及重新调度,互斥锁不能用在原子上下文中,如Tasklet和定时器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值