精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux中的傷害/等待互斥鎖介紹

Linux閱碼場 ? 來源:Linux驛站 ? 作者:szyhb1981 ? 2021-11-06 17:27 ? 次閱讀
序言:近期讀Linux 5.15的發布說明,該版本合并了實時鎖機制,當開啟配置宏CONFIG_PREEMPT_RT的時候,這些鎖被基于實時互斥鎖的變體替代:mutex、ww_mutexrw_semaphorespinlock和rwlock。第一次聽說ww_mutex,在百度上查找的時候發現介紹文檔很少,于是自己學習,寫成筆記。在某些場合必須同時持有多個鎖,并且獲取鎖的順序可能不同,為了避免死鎖,應該使用傷害/等待互斥鎖(Wound/Wait Mutexes)。獲取一個鎖集合稱為一個事務(transaction),每個事務關聯一張門票(ticket),門票也稱為序列號,根據門票判斷哪個事務年輕。有2種處理死鎖的方法,如下。(1)等待-死亡(Wait-Die)算法:一個事務申請另一個事務已經獲取的鎖的時候,如果持有鎖的事務年輕,那么申請鎖的事務等待(wait);如果持有鎖的事務年老,那么申請鎖的事務退并且死亡(die)

(2) 4.19版本開始支持傷害-等待(Wound-Wait)算法:一個事務申請另一個事務已經獲取的鎖的時候,如果持有鎖的事務年輕,那么申請鎖的事務傷害(wound)持有鎖的事務,請求它去死亡;如果持有鎖的事務年老,那么申請鎖的事務等待(wait)

假設進程1和進程2分別在2個處理器上運行,進程1獲取鎖A,進程2獲取鎖B,然后進程1申請鎖B,進程2申請鎖A。假設進程1的門票編號比進程2的門票編號小,也就是進程1年老,進程2年輕。假設選擇等待-死亡算法。年老的進程1申請鎖B,發現持有鎖B的進程2年輕,那么年老的進程1等待。年輕的進程2申請鎖A,發現持有鎖A的進程1年老,那么年輕的進程2死亡(即申請鎖的函數返回“-EDEADLK”),接著回滾(即釋放已經獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B(必須改變申請順序,如果先申請鎖B,那么會把剛釋放的鎖B搶回來)。假設選擇傷害-等待算法。年老的進程1申請鎖B,發現持有鎖B的進程2年輕,那么傷害年輕的進程2,請求它死亡。年輕的進程2申請鎖A,發現持有鎖A的進程1年老,那么年輕的進程2等待,在收到進程1的死亡請求以后,年輕的進程2死亡(即申請鎖的函數返回“-EDEADLK”),接著回滾(即釋放已經獲取的鎖B),然后重新開始:先申請鎖A然后申請鎖B。兩種算法都是公平的,因為其中一個事務最終會成功。和等待-死亡算法相比,傷害-等待算法生成的退避少,但是從一次退避恢復的時候要做更多的工作。傷害-等待算法是一種搶占性的算法(因為事務被其它事務傷害),需要一種可靠的方法來選擇受傷狀態和搶占正在運行的事務。在傷害-等待算法中,一個事務在受傷后死亡(返回“-EDEADLK”),就認為這個事務被搶占。如果競爭鎖的進程少,并且希望減少回滾的次數,那么應該選擇傷害-等待算法。 和普通的互斥鎖相比,傷害/等待互斥鎖增加了下面2個概念。

(1)獲取上下文acquire context):一個獲取上下文表示一個事務,關聯一張門票(ticket),門票也稱為序列號,門票編號小表示年老,門票編號大表示年輕。獲取上下文跟蹤調試狀態,捕獲對傷害/等待互斥鎖接口的錯誤使用。

(2)傷害/等待類初始化獲取上下文的時候需要指定鎖類,鎖類會給獲取上下文分配門票。鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。當多個進程競爭同一個鎖集合的時候,它們必須使用相同的鎖類。

3種獲取傷害/等待互斥鎖的函數,如下。

(1) 普通的獲取鎖函數ww_mutex_lock(),帶有獲取上下文。

(2) 進程在回滾(即釋放所有已經獲取的鎖)以后,使用慢路徑獲取鎖函數ww_mutex_lock_slow()獲取正在競爭的鎖。帶有“_slow”后綴的函數不是必需的,因為可以調用函數ww_mutex_lock()獲取正在競爭的鎖。帶有“_slow”后綴的函數的優點是接口安全,如下。

  • 函數ww_mutex_lock()有一個整數返回值,而函數ww_mutex_lock_slow()沒有返回值。
  • 當開啟調試的時候,函數ww_mutex_lock_slow()檢查所有已經獲取的鎖已經被釋放,并且確保進程阻塞在正在競爭的鎖上面。

(3) 只獲取一個傷害/等待互斥鎖,和獲取普通的互斥鎖完全相同。調用函數ww_mutex_lock(),把獲取上下文指定為空指針。

傷害/等待互斥鎖的使用方法如下。

(1) 定義一個鎖類,鎖類在初始化獲取上下文的時候需要,鎖類也指定算法:等待-死亡(Wait-Die)或傷害-等待(Wound-Wait)。

/* 指定等待-死亡算法 */static DEFINE_WD_CLASS(my_class);
/* 指定傷害-等待算法 */staticDEFINE_WW_CLASS(my_class);

(2) 初始化一個獲取上下文,鎖類會給獲取上下文分配一張門票。

void ww_acquire_init(struct ww_acquire_ctx *ctx, struct ww_class *ww_class);
(3) 獲取鎖,返回0表示獲取成功,返回“-EDEADLK”表示檢測出死鎖。
int ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx);
(4) 獲取需要的所有鎖以后,標記獲取階段結束。目前這個函數沒有執行任何操作,但是將來可能改變。
void ww_acquire_done(struct ww_acquire_ctx *ctx);
(5) 釋放鎖。
void ww_mutex_unlock(struct ww_mutex *lock);
(6) 釋放所有鎖以后,釋放獲取上下文。
void ww_acquire_fini(struct ww_acquire_ctx *ctx);

下面是一個例子,注意:調用函數ww_mutex_lock()申請鎖失敗以后,應該先釋放已經獲取的鎖,然后調用慢路徑函數ww_mutex_lock_slow()獲取正在競爭的鎖,最后獲取其它鎖。重新開始申請鎖的時候必須改變申請順序,因為如果按照原來的順序申請鎖,那么會把剛釋放的鎖搶回來。
/* 第1步:定義鎖類,指定傷害-等待算法。*/static DEFINE_WW_CLASS(ww_class);
struct obj {  struct ww_mutex lock;  /* obj data */};
struct obj_entry {  struct list_head head;  struct obj *obj;};
int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx){  struct obj *res_obj = NULL;  struct obj_entry *contended_entry = NULL;  struct obj_entry *entry;  int ret;
  /* 第2步:初始化獲取上下文。*/  ww_acquire_init(ctx, &ww_class);
  /* 第3步:獲取鎖。*/retry:  list_for_each_entry(entry, list, head) {    if (entry->obj == res_obj) {      res_obj = NULL;      continue;    }
    ret = ww_mutex_lock(&entry->obj->lock, ctx);    if (ret < 0) {      contended_entry = entry;      goto err;    }  }
  /* 第4步:標記獲取階段結束。*/  ww_acquire_done(ctx);  return 0;
err:  /* 回滾,釋放已經獲取的鎖。*/  list_for_each_entry_continue_reverse(entry, list, head) {    ww_mutex_unlock(&entry->obj->lock);  }
  if (res_obj) {    ww_mutex_unlock(&res_obj->lock);  }
  if (ret == -EDEADLK) {    /* 使用慢路徑獲取鎖函數獲取正在競爭的鎖。*/    ww_mutex_lock_slow(&contended_entry->obj->lock, ctx);    res_obj = contended_entry->obj;    /* 獲取其它鎖。*/    goto retry;  }  ww_acquire_fini(ctx);
  return ret;}
void unlock_objs(struct list_head *list, struct ww_acquire_ctx *ctx){  struct obj_entry *entry;
  /* 第5步:釋放鎖。*/  list_for_each_entry (entry, list, head) {    ww_mutex_unlock(&entry->obj->lock);  }
  /* 第6步:釋放獲取上下文。*/  ww_acquire_fini(ctx);}
責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鎖相環
    +關注

    關注

    35

    文章

    583

    瀏覽量

    87699
  • Linux
    +關注

    關注

    87

    文章

    11232

    瀏覽量

    208957

原文標題:傷害/等待互斥鎖

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    互斥和自旋的實現原理

    保護共享資源不被多個線程同時訪問。它的實現原理主要包括以下幾個方面: 1. 的初始化 互斥鎖在創建時需要進行初始化,通常包括設置的狀態為“未鎖定”。在某些實現,還需要初始化
    的頭像 發表于 07-10 10:07 ?420次閱讀

    自旋互斥的使用場景是什么

    自旋互斥是兩種常見的同步機制,它們在多線程編程中被廣泛使用。在本文中,我們將介紹自旋互斥
    的頭像 發表于 07-10 10:05 ?905次閱讀

    B系列推拉自連接器介紹

    電子發燒友網站提供《B系列推拉自連接器介紹.pdf》資料免費下載
    發表于 07-01 13:09 ?0次下載

    小米汽車推出等待關懷計劃,為用戶送上暖心禮遇

    在如今的汽車市場,消費者對于交付周期的長短越來越敏感。為了回饋那些因車輛交付周期長而需要耐心等待的用戶,小米汽車近日在其APP更新推出了一項備受矚目的新政策——“
    的頭像 發表于 06-29 15:54 ?1653次閱讀

    介紹一種嵌入式Linux的錄音降噪方案

    降噪不僅只能從硬件入手,本文為您介紹一種嵌入式Linux的錄音降噪方案。該方案完全依靠軟件實現,最大程度上降低投入。
    的頭像 發表于 05-21 11:52 ?531次閱讀

    關于FreeRTOS互斥量的用法求解

    會引起死,比如當同一個任務多次搶占時, 最后還是得換到互斥量, 基于串口中斷發送模式, 希望使用互斥量來訪問串口的話 , 該如何釋放發送完成信號呢? 在中斷函數釋放
    發表于 04-24 08:03

    RTThread4.1.1在spiflash上掛dfs文件系統報互斥錯誤的原因?

    最近使用gd32f450vg芯片,在SPI4接口上掛了gd25q32,想使用dfs文件系統,gd25q32能夠正常的識別,顯示文件系統掛載正常,但是只要操作文件系統就會出現報錯,看像是互斥的問題,請問這個要從哪個方向查原因
    發表于 03-05 07:39

    如何解決Linux系統的網絡連接問題?

    如何解決Linux系統的網絡連接問題? Linux系統的網絡連接問題是常見的技術難題之一,通常涉及在Linux上配置網絡接口、解決網絡故
    的頭像 發表于 01-12 15:17 ?907次閱讀

    信號量實現原理介紹

    除了原子操作,中斷屏蔽,自旋以及自旋的衍生之外,在Linux內核還存在著一些其他同步互斥
    的頭像 發表于 01-10 09:07 ?1110次閱讀

    Linux內核RCU的用法

    Linux內核,RCU最常見的用途是替換讀寫。在20世紀90年代初期,Paul在實現通用RCU之前,實現了一種輕量級的讀寫。后來,為這個輕量級讀寫
    的頭像 發表于 12-27 09:56 ?1676次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>中</b>RCU的用法

    redis分布式的缺點

    :Redis分布式無法保證絕對的精確性和一致性。由于分布式系統的網絡延遲、故障和并發訪問等因素的存在,的獲得和釋放可能不是完全同步的。這可能導致某些線程或進程在未獲得的情況下繼
    的頭像 發表于 12-04 14:05 ?1217次閱讀

    淺析Redis 分布式解決方案

    來訪問共享資源,而分布式可以提供一個簡單而有效的方式來實現這種協調。 引言 在分布式系統,多個服務同時訪問共享資源時,需要一種機制來保證對資源的訪問是線程安全的。傳統的互斥機制,如使用數據庫
    的頭像 發表于 12-04 14:00 ?466次閱讀

    如何實現Redis分布式

    機制,下面將詳細介紹如何實現Redis分布式。 一、引言 在分布式系統,多個節點可能同時讀寫同一共享資源。如果沒有實現互斥訪問和同步機制,就會產生數據不一致和競態條件等問題。解決這
    的頭像 發表于 12-04 11:24 ?668次閱讀

    redis機制原理

    Redis是一款高性能的開源內存數據庫,用于存儲和檢索數據。在多線程或分布式環境,需要實現并發控制來保證數據一致性和線程安全。Redis提供了一種簡單而高效的機制,可以用來實現并發控制
    的頭像 發表于 12-04 11:08 ?1202次閱讀

    Linux讀寫邏輯解析—Linux為何會引入讀寫

    除了mutex,在linux內核,還有一個經常用到的睡眠就是rw semaphore(后文簡稱為rwsem),它到底和mutex有什么不同呢?
    的頭像 發表于 12-04 11:04 ?876次閱讀
    <b class='flag-5'>Linux</b>讀寫<b class='flag-5'>鎖</b>邏輯解析—<b class='flag-5'>Linux</b>為何會引入讀寫<b class='flag-5'>鎖</b>?