互斥體是什么?
互斥體是Linux內(nèi)核專門設(shè)計(jì)的同步機(jī)制,用于實(shí)現(xiàn)“一次僅一個(gè)線程訪問共享資源”的互斥控制。相比通過將信號(hào)量值設(shè)為 1 來模擬互斥,mutex 的語義更清晰、行為更規(guī)范,是驅(qū)動(dòng)開發(fā)中保護(hù)臨界區(qū)的首選方案。
核心特性:同一時(shí)刻只允許一個(gè)線程持有 mutex,進(jìn)入臨界區(qū),其他線程必須等待
不可遞歸:mutex 不支持同一線程重復(fù)加鎖,重復(fù)上鎖會(huì)導(dǎo)致死鎖。
適用場(chǎng)景:編寫Linux驅(qū)動(dòng)程序時(shí),如需保護(hù)硬件寄存器操作、設(shè)備打開關(guān)閉等獨(dú)占性操作,應(yīng)優(yōu)先使用 mutex。
Linux 內(nèi)核中,mutex 由structmutex結(jié)構(gòu)體表示,核心成員包括:
atomic_tcount:記錄鎖狀態(tài),1 表示未上鎖,0 表示已上鎖,負(fù)數(shù)表示已上鎖且有等待者。
spinlock_t wait_lock:保護(hù)等待隊(duì)列的自旋鎖,用于協(xié)調(diào)等待線程。
注:現(xiàn)代內(nèi)核的 mutex 實(shí)現(xiàn)更復(fù)雜,引入了樂觀自旋、MCS 鎖隊(duì)列等優(yōu)化,提升多核性能,但核心原理不變。
使用注意事項(xiàng):
禁止用于中斷上下文:mutex 加鎖過程可能導(dǎo)致線程休眠,而中斷上下文不允許休眠,否則引發(fā)系統(tǒng)崩潰。中斷場(chǎng)景下應(yīng)使用自旋鎖。
臨界區(qū)支持阻塞操作:mutex 允許休眠,因此臨界區(qū)內(nèi)可安全調(diào)用 copy_from_user()、msleep()、kmalloc(GFP_KERNEL)等可能阻塞的函數(shù)。
嚴(yán)格遵循所有權(quán):只有持有 mutex 的線程才能解鎖,禁止遞歸加鎖和跨線程解鎖,否則會(huì)導(dǎo)致死鎖或邏輯錯(cuò)誤。
互斥體 API 函數(shù)
Linux 內(nèi)核提供了一組簡(jiǎn)潔的 mutex 操作接口,核心函數(shù)如下:
DEFINE_MUTEX(name):靜態(tài)定義并初始化一個(gè) mutex 變量,推薦優(yōu)先使用,一步完成定義和初始化。
mutex_init(struct mutex *lock):動(dòng)態(tài)初始化已定義的 mutex,常用于結(jié)構(gòu)體內(nèi)嵌 mutex 的場(chǎng)景。
mutex_lock(struct mutex *lock):獲取 mutex,若已被占用則線程進(jìn)入不可中斷的休眠狀態(tài)等待,成功獲取后進(jìn)入臨界區(qū)。
mutex_unlock(struct mutex *lock):釋放 mutex,喚醒等待隊(duì)列中的第一個(gè)線程,退出臨界區(qū)。
mutex_lock_interruptible(struct mutex *lock):可被信號(hào)中斷的加鎖函數(shù),若等待期間收到信號(hào)則返回 -EINTR,適合需要響應(yīng)用戶信號(hào)的場(chǎng)景(如驅(qū)動(dòng)的系統(tǒng)調(diào)用)。
mutex_trylock(struct mutex *lock):非阻塞嘗試獲取 mutex,成功返回 1,失敗返回 0,不會(huì)休眠,適合需要快速判斷的場(chǎng)景。
mutex_is_locked(struct mutex *lock):檢查 mutex 是否已被持有,返回 1 表示已上鎖,0 表示未上鎖。
互斥體使用示例
方式1:
動(dòng)態(tài)初始化struct mutex lock;mutex_init(&lock);
方式2:
靜態(tài)初始化(推薦)
DEFINE_MUTEX(my_lock);// 加鎖
進(jìn)入臨界區(qū)
mutex_lock(&lock);// 臨界區(qū):
訪問共享資源,執(zhí)行獨(dú)占操作
mutex_unlock(&lock); // 解鎖,退出臨界區(qū)
核心對(duì)比:
mutex、信號(hào)量與自旋鎖
mutex:專為互斥設(shè)計(jì),支持休眠,不可用于中斷,有嚴(yán)格的所有權(quán)語義,適合驅(qū)動(dòng)開發(fā)中長(zhǎng)臨界區(qū)的場(chǎng)景,是互斥訪問的首選。
二值信號(hào)量:可用于互斥,但語義不如 mutex 清晰,允許任意線程釋放,且支持遞歸加鎖,更適合通用同步場(chǎng)景,而非單純的互斥控制。
自旋鎖:不可休眠,通過忙等實(shí)現(xiàn)互斥,性能極高,適合短臨界區(qū)且支持中斷上下文,但會(huì)占用 CPU 資源,不能用于可能休眠的場(chǎng)景。
總結(jié)
mutex 是 Linux 內(nèi)核為互斥場(chǎng)景量身定制的同步機(jī)制,語義明確、安全性高,是驅(qū)動(dòng)開發(fā)中保護(hù)設(shè)備獨(dú)占訪問的核心工具。使用時(shí)需牢記:禁止在中斷上下文使用、禁止遞歸加鎖、嚴(yán)格遵循“誰加鎖誰解鎖”的原則。實(shí)際開發(fā)中,配合內(nèi)核調(diào)試選項(xiàng)可有效檢測(cè)死鎖和誤用問題,保障代碼可靠性。