天天看點

kernel互斥鎖mutex

互斥鎖主要用于實作核心中的互斥通路功能。核心互斥鎖是在原子 API 之上實作的,但這對于核心使用者是不可見的。對它的通路必須遵循一些規則:同一時間隻能有一個任務持有互斥鎖,而且隻有這個任務可以對互斥鎖進行解鎖。互斥鎖不能進行遞歸鎖定或解鎖。一個互斥鎖對象必須通過其API初始化,一個任務在持有互斥鎖的時候是不能結束的,互斥鎖所使用的記憶體區域是不能被釋放的,使用中的互斥鎖是不能被重新初始化的,并且互斥鎖不能用于中斷上下文。互斥鎖比核心信号量更快,并且更加緊湊,是以如果它們滿足您的需求,那麼它們将是您明智的選擇。

/linux/include/linux/mutex.h

struct mutex {

          atomic_t                count;

          spinlock_t              wait_lock;

          struct list_head        wait_list;

  #ifdef CONFIG_DEBUG_MUTEXES

          struct thread_info      *owner;

          const char              *name;

          void                    *magic;

  #endif

  #ifdef CONFIG_DEBUG_LOCK_ALLOC

          struct lockdep_map      dep_map;

  #endif

  };

count訓示互斥鎖的狀态:

     1 沒有上鎖,可以獲得

     0 被鎖定,不能獲得

     負數 被鎖定,且可能在該鎖上有等待程序,初始化為沒有上鎖。

wait_lock等待擷取互斥鎖時使用的自旋鎖。在擷取互斥鎖的過程中,操作會在自旋鎖的保護中進行。初始化為為鎖定。

wait_list等待互斥鎖的程序隊列。

相關API:

1、定義并初始化:

struct mutex mutex;

mutex_init(&mutex);

2、擷取互斥鎖:

(1)具體參見linux/kernel/mutex.c

void inline fastcall __sched mutex_lock(struct mutex *lock);

首先取得count的值,在将count置-1,判斷如果原來count的置為1,也即互斥鎖可以獲得,則直接擷取然後跳出。否則進入循環反複測試互斥鎖的狀态。在循環中,同樣先取得互斥鎖原來的狀态,在将其-1,如果可以擷取(等于1),則退出循環,否則設定目前程序的狀态為不可中斷狀态,解鎖自身的自旋鎖,進入睡眠狀态,待被再排程喚醒時,再獲得自身的自旋鎖,進入新一次的查詢其自身狀态(該互斥鎖的狀态)的循環。

(2)具體參見linux/kernel/mutex.c

int fastcall __sched mutex_lock_interruptible(struct mutex *lock);

和mutex_lock()一樣,在獲得了互斥鎖後會傳回0。如果在等待擷取鎖的時候進入睡眠狀态并收到一個信号(被信号打斷睡眠),則傳回-EINIR。

(3)具體參見linux/kernel/mutex.c

int fastcall __sched mutex_trylock(struct mutex *lock);

試圖擷取互斥鎖,如果成功擷取則傳回1,否則傳回0,不等待。

3、釋放互斥鎖:

具體參見linux/kernel/mutex.c

void fastcall mutex_unlock(struct mutex *lock);

釋放被目前程序擷取的互斥鎖。該函數不能用在中斷上下文中,而且不允許去釋放一個沒有上鎖的互斥鎖。

繼續閱讀