mutex(互斥锁)是Linux内核中最常用的同步机制之一,用于保护临界区资源,防止多个执行路径同时访问共享数据。下面我将深入分析mutex在内核中的实现。
在Linux内核中,mutex定义在include/linux/mutex.h
中:
struct mutex {
atomic_long_t owner;
spinlock_t wait_lock;
struct list_head wait_list;
};
owner:原子长整型,表示当前锁的拥有者
wait_lock:自旋锁,用于保护wait_list的访问
wait_list:等待获取该mutex的任务链表
owner字段的低3位用作状态标志:
#define MUTEX_FLAG_WAITERS 0x01 // 有任务在等待队列中
#define MUTEX_FLAG_HANDOFF 0x02 // 需要传递所有权
#define MUTEX_FLAG_PICKUP 0x04 // 准备接收所有权
void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
atomic_long_set(&lock->owner, 0);
spin_lock_init(&lock->wait_lock);
INIT_LIST_HEAD(&lock->wait_list);
}
void __sched mutex_lock(struct mutex *lock)
{
might_sleep();
if (!__mutex_trylock_fast(lock))
__mutex_lock_slowpath(lock);
}
void __sched mutex_unlock(struct mutex *lock)
{
if (__mutex_unlock_fast(lock))
return;
__mutex_unlock_slowpath(lock);
}
当mutex被其他CPU持有但持有者正在运行时,当前CPU不会立即睡眠,而是会自旋等待一小段时间,这可以减少上下文切换的开销。
当高优先级任务需要获取已被低优先级任务持有的mutex时,内核会通过MUTEX_FLAG_HANDOFF
标志实现锁的传递,避免优先级反转问题。
#include <linux/mutex.h>
struct my_data {
struct mutex lock;
int shared_data;
};
void init_data(struct my_data *data)
{
mutex_init(&data->lock);
data->shared_data = 0;
}
void modify_data(struct my_data *data, int new_value)
{
mutex_lock(&data->lock);
data->shared_data = new_value;
mutex_unlock(&data->lock);
}
mutex是Linux内核中精心优化的同步原语,理解其内部实现有助于编写更高效和安全的内核代码。