淺析 task_struct 中自旋鎖的應(yīng)用

自旋鎖是用于保護(hù)短的代碼片段,其中只包含少量C語句,因此會很快執(zhí)行完畢。大多數(shù)內(nèi)核數(shù)據(jù)結(jié)構(gòu)都有自身的自旋鎖,在處理結(jié)構(gòu)中的關(guān)鍵成員時,必須獲得相應(yīng)的自旋鎖。

定義自旋鎖

struct task_struct {
     ...
     /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
     spinlock_t alloc_lock;
     ...
1757 /*                                                                          
1758  * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring           
1759  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
1760  * pins the final release of task.io_context.  Also protects ->cpuset and    
1761  * ->cgroup.subsys[].                                                      
1762  *                                                                                                              
1763  * Nests both inside and outside of read_lock(&tasklist_lock).         
1764  * It must not be nested with write_lock_irq(&tasklist_lock),                                  
1765  * neither inside nor outside.                                   
1766  */ 

初始化自旋鎖

./kernel/fork.c:1049:    spin_lock_init(&p->alloc_lock);

獲取自旋鎖

1767 static inline void task_lock(struct task_struct *p)              
1768 {                                                                 
1769     spin_lock(&p->alloc_lock);                                      
1770 }    

釋放自旋鎖

1772 static inline void task_unlock(struct task_struct *p)          
1773 {                                                              
1774     spin_unlock(&p->alloc_lock);           
1775 }

自旋鎖的使用

在處理 task_struct 結(jié)構(gòu)中的 ptrace / files / active_mm / mm / flags / cgroups / io_context 等關(guān)鍵成員時,需要獲取 alloc_lock 自旋鎖。

void foo()
{
    task_lock(current);
    // 處理 task_struct 結(jié)構(gòu)的關(guān)鍵成員
    task_unlock(current);
}

為什么這么多關(guān)鍵成員都使用同一個 alloc_lock 自旋鎖呢? 不會影響性能嗎? 為什么不使用不同的自旋鎖呢?
個人理解:因為使用 alloc_lock 所保護(hù)的關(guān)鍵成員操作并不頻繁,而且操作的時間點(diǎn)并不集中,所以不會影響性能。

自旋鎖用來在多處理器的環(huán)境下保護(hù)數(shù)據(jù)。如果內(nèi)核發(fā)現(xiàn)數(shù)據(jù)未鎖,就獲取鎖并運(yùn)行;如果數(shù)據(jù)已鎖,就一直旋轉(zhuǎn),其實是一直反復(fù)執(zhí)行一條指令。之所以說自旋鎖用在多處理器環(huán)境,是因為在單處理器環(huán)境(非搶占式內(nèi)核)下,自旋鎖其實不起作用。在單處理器搶占式內(nèi)核的情況下,自旋鎖起到禁止搶占的作用。
因為被自旋鎖鎖著的進(jìn)程一直旋轉(zhuǎn),而不是睡眠,所以自旋鎖可以用在中斷等禁止睡眠的場景。

spin_lock 會考慮下面兩種情況:

  • 如果內(nèi)核中其他地方尚未獲得 lock,則有當(dāng)前處理器獲取。其它處理器不能再進(jìn)入 lock 保護(hù)的代碼范圍。
  • 如果 lock 已經(jīng)由另一個處理器獲得,spin_lock 進(jìn)入一個無限循環(huán),重復(fù)地檢查 lock 是否已經(jīng)由 spin_unlock 釋放(自旋鎖因此得名)。如果已經(jīng)釋放,則獲得 lock ,并進(jìn)入臨界區(qū)。

在使用自旋鎖時必須要注意下面兩點(diǎn)。

  • 如果獲得鎖之后不釋放,系統(tǒng)將變的不可用。所有的處理器(包括獲得鎖的在內(nèi)),遲早需要進(jìn)入對應(yīng)的臨界區(qū)。它們會進(jìn)入無限循環(huán)等待鎖釋放,但等不到。便產(chǎn)生了死鎖。
  • 自旋鎖絕不應(yīng)該長期持有,因為所有等待釋放鎖的處理器都處于不可用狀態(tài),無法用于其他工作(信號量的情形有所不同)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容