互斥体概述
信号量是在并行处理环境中对多个处理器访问某个公共资源进行保护的机制,mutex用于互斥操作。信号量的count初始化为1,down()/up()也可以实现类似mutex的作用。
mutex的语义相对于信号量要简单轻便一些,在锁争用激烈的测试场景下,mutex比信号量执行速度更快,可扩展性更好,另外mutex数据结构的定义比信号量小。
mutex的优点
- mutex和信号量相比要高效的多:
- mutex最先实现自旋等待机制
- mutex在睡眠之前尝试获取锁
- mutex实现MCS所来避免多个CPU争用锁而导致CPU高速缓存颠簸现象。
mutex的使用注意事项:
- 同一时刻只有一个线程可以持有mutex。
- 只有锁持有者可以解锁。不能再一个进程中持有mutex,在另外一个进程中释放他。
- 不允许递归地加锁和解锁。
- 当进程持有mutex时,进程不可以退出。
- mutex必须使用官方API来初始化。
- mutex可以睡眠,所以不允许在中断处理程序或者中断下半部中使用,例如tasklet、定时器等。
目录:
- /linux/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 {
- /* 1: unlocked, 0: locked, negative: locked, possible waiters */
- atomic_t count;
- spinlock_t wait_lock;
- struct list_head wait_list;
- #if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
- struct task_struct *owner;
- #endif
- #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
- void *spin_mlock; /* Spinner MCS lock */
- #endif
- #ifdef CONFIG_DEBUG_MUTEXES
- const char *name;
- void *magic;
- #endif
- #ifdef CONFIG_DEBUG_LOCK_ALLOC
- struct lockdep_map dep_map;
- #endif
- };
作用及访问规则:
- 互斥锁主要用于实现内核中的互斥访问功能。内核互斥锁是在原子 API 之上实现的,但这对于内核用户是不可见的。
- 对它的访问必须遵循一些规则:同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行解锁。互斥锁不能进行递归锁定或解锁。一个互斥锁对象必须通过其API初始化,而不能使用memset或复制初始化。一个任务在持有互斥锁的时候是不能结束的。互斥锁所使用的内存区域是不能被释放的。使用中的互斥锁是不能被重新初始化的。并且互斥锁不能用于中断上下文。
- 互斥锁比当前的内核信号量选项更快,并且更加紧凑。