信號量、互斥鎖、自旋鎖、原子操作

来源:http://www.cnblogs.com/linhaostudy/archive/2017/09/07/6670693.html
-Advertisement-
Play Games

linux內核中有多種內核鎖,內核鎖的作用是: 多核處理器下,會存在多個進程處於內核態的情況,而在內核態下,進程是可以訪問所有內核數據的,因此要對共用數據進行保護,即互斥處理; linux內核鎖機制有信號量、互斥鎖、自旋鎖還有原子操作。 一、信號量(struct semaphore): 是用來解決進 ...


linux內核中有多種內核鎖,內核鎖的作用是:

多核處理器下,會存在多個進程處於內核態的情況,而在內核態下,進程是可以訪問所有內核數據的,因此要對共用數據進行保護,即互斥處理;  

linux內核鎖機制有信號量互斥鎖自旋鎖還有原子操作

 

一、信號量(struct semaphore):

是用來解決進程/線程之間的同步和互斥問題的一種通信機制,是用來保證兩個或多個關鍵代碼不被併發調用。

信號量(Saphore)由一個值和一個指針組成,指針指向等待該信號量的進程。信號量的值表示相應資源的使用情況。信號量S>=0時,S表示可用資源的數量。執行一次P操作意味著請求分配一個資源,因此S的值減1;當S<0時,表示已經沒有可用資源,S的絕對值表示當前等待該資源的進程數。請求者必須等待其他進程釋放該類資源,才能繼續運行。而執行一個V操作意味著釋放一個資源,因此S的值加1;若S<0,表示有某些進程正在等待該資源,因此要喚醒一個等待狀態的進程,使之運行下去。 

信號量是選擇睡眠的方式來對共用工作停止訪問的。

也就是說信號量通過PV操作同步解決了進程/線程對臨界資源利用的衝突問題;

 

二、互斥鎖:(mutex_lock)

互斥鎖同樣也是對線程間(不能對進程)同步和互斥的一種另一種機制。

互斥鎖更多的是強調對共用資源的鎖定作用,當一個線程占用了當前共用資源,使用互斥鎖將其lock住之後,其他線程就無法訪問,必須等到unlock之後,其他線程才能利用共用資源裡面的內容;

 互斥鎖是選擇睡眠的方式來對共用工作停止訪問的。

也就是說互斥鎖通過對共用資源的鎖定和互斥解決利用資源衝突問題;

 

 

 三、自旋鎖(spin_lock):

是為實現保護共用資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為瞭解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對於互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直迴圈在那裡看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。

 

 

四、原子操作:

Reference:

http://blog.sina.com.cn/s/blog_6d7fa49b01014q7p.html

http://blog.csdn.net/vividonly/article/details/6599502

http://blog.csdn.net/williamwang2013/article/details/8517380

http://blog.csdn.net/yikai2009/article/details/8650221

4.1、Linux原子概念:

所謂原子操作,就是“不可中斷的一個或一系列操作”。

原子操作,就是不能被更高等級中斷搶奪優先的操作。你既然提這個問題,我就說深一點。由於操作系統大部分時間處於開中斷狀態,所以,一個程式在執行的時候可能被優先順序更高的線程中斷。而有些操作是不能被中斷的,不然會出現無法還原的後果,這時候,這些操作就需要原子操作。就是不能被中斷的操作。

硬體級的原子操作:在單處理器系統(UniProcessor)中,能夠在單條指令中完成的操作都可以認為是“原子操作”,因為中斷只發生在指令邊緣。在多處理器結構中(Symmetric Multi-Processor)就不同了,由於系統中有多個處理器獨立運行,即使能在單條指令中完成的操作也有可能受到干擾。在X86平臺生,CPU提供了在指令執行期間對匯流排加鎖的手段。CPU上有一根引線#HLOCK pin連到北橋,如果彙編語言的程式中在一條指令前面加上首碼"LOCK",經過彙編以後的機器代碼就使CPU在執行這條指令的時候把#HLOCK pin的電位拉低,持續到這條指令結束時放開,從而把匯流排鎖住,這樣同一匯流排上別的CPU就暫時不能通過匯流排訪問記憶體了,保證了這條指令在多處理器環境中的原子性。對於其他平臺的CPU,實現各不相同,有的是通過關中斷來實現原子操作(sparc),有的通過CMPXCHG系列的指令來實現原子操作(IA64)。本文主要探討X86平臺下原子操作的實現。

 

 

4.2、Linux內核兩組原子操作介面:

1、原子整數操作

原子操作通常針對int或bit類型的數據,但是Linux並不能直接對int進行原子操作,而只能通過atomic_t的數據結構來進行。

定義於#include<asm/atomic.h>

圖1.1      內核中的整數原子操作函數

 

2、內核中提供的一些主要位原子操作函數。同時內核還提供了一組與上述操作對應的非原子位操作函數,名字前多兩下劃線。由於不保證原子性,因此速度可能執行更快。

定義於#include<asm/bitops.h>

大話Linux內核中鎖機制之原子操作、自旋鎖

圖1.2      內核中的位原子操作函數

 

 1 void atomic_set(atomic_t *v,int i);    //設置原子變數v的值為i
 2 atomic_t v = ATOMIC_INIT(0);     //定義原子變數v,並初始化為0;
 3 
 4 atomic_read(atomic_t* v);     //返回原子變數v的值;
 5 
 6 void atomic_add(int i, atomic_t* v);     //原子變數v增加i;
 7 void atomic_sub(int i, atomic_t* v);    
 8 
 9 void atomic_inc(atomic_t* v);     //原子變數增加1;
10 void atomic_dec(atomic_t* v);     
11 
12 int atomic_inc_and_test(atomic_t* v);        //先自增1,然後測試其值是否為0,若為0,則返回true,否則返回false;
13 int atomic_dec_and_test(atomic_t* v);       //先自減1,然後測試其值是否為0,若為0,則返回true,否則返回false 
14 int atomic_sub_and_test(int i, atomic_t* v);     //先減i,然後測試其值是否為0,若為0,則返回true,否則返回false;
15 //註意:只有自加,沒有加操作
16 
17 int atomic_add_return(int i, atomic_t* v);   //v的值加i後返回新的值;
18 int atomic_sub_return(int i, atomic_t* v);  
19 int atomic_inc_return(atomic_t* v);     //v的值自增1後返回新的值;
20 int atomic_dec_return(atomic_t* v);    

 

實例代碼:

在scull_open 函數和scull_close函數中:

如果沒有進程使用該驅動 ,原子變數值 為 1 ,將原子變數減 一 為 0 ,函數返回 true ,再 !true 為 假 ,if 裡面的代碼不執行這樣打開了、並使用該驅動, 原子變數變為 0;

如果再有進程來打開驅動程式,0-1 = 負1,返回 false ,if 條件成立,運行裡面的代碼,將原子變數加一恢復到  0,程式返回;

最後, 在應用程式退出時 close 函數, 自增 恢複原子變數值為 1:

 1 static atomic_t scull_available = ATOMIC_INIT(1);      //init atomic
 2 
 3 int scull_open(struct inode *inode, struct file *filp)
 4 {
 5     struct scull_dev *dev;         // device information
 6 
 7     dev = container_of(inode->i_cdev, struct scull_dev, cdev);
 8     filp->private_data = dev;         // for other methods 
 9     if(!atomic_dec_and_test(&scull_available)){
10         atomic_inc(&scull_available);
11         return -EBUSY;
12     }
13     return 0;         // success 
14 }
15 
16 int scull_release(struct inode *inode, struct file *filp)
17 {
18     atomic_inc(&scull_available);
19     return 0;
20 }

 

 

 

 

 

以上總結幾點:

互斥鎖與信號量的區別:

1、信號量一般以同步的方式對共用資源進行控制,而互斥鎖通過互斥的方式對共用資源對其進行控制;

2、信號量可以對進程的共用資源進行控制,而互斥鎖不行;

3、信號量的值為非負整數,而互斥鎖的值只能為0或1;

4、互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量可以由一個線程釋放,另一個線程得到;

 

自旋鎖與互斥鎖的區別:

1、因為自旋鎖不會引起調用者睡眠,所以效率比較高

2、自旋鎖比較適用於鎖使用者保持鎖時間比較短的情況。

3、自旋鎖容易造成死鎖,所以需要安全使用它;

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天在使用taskctl的designer時,十多分鐘掛了2次,每次掛了之後就簽不出來了,只能等半小時,然後在taskctl的QQ群里咨詢了,給的解決方案是 http://www.taskctl.com/forum/detail_58.html ,我按照步驟操作時發現ctladmin登錄不了,在群里 ...
  • 一、約束之主鍵約束 約束:約束是添加在列上的,用來約束列的。 1、主鍵約束(唯一標識):非空、唯一、被引用 當表的某一列被指定為主鍵後,該類就不能為空,不能有重覆值出現 創建表時指定主鍵的兩種方式: 指定sid列為主鍵列,即為sid列添加主鍵約束 修改表時指定主鍵: ALTER TABLE stu ...
  • 一、表格 表一 emp 表二 dept 表三 salgrade; 表四 年度利潤表 二、習題 1. 查出至少有一個員工的部門。顯示部門編號、部門名稱、部門位置、部門人數。 2. 列出所有員工的姓名及其直接上級的姓名。 3. 列出受雇日期早於直接上級的所有員工的編號、姓名、部門名稱。 4. 列出部門名 ...
  • 什麼是Database,什麼是Schema,什麼是Table,什麼是列,什麼是行,什麼是User? 我們可以把Database看作是一個大倉庫,倉庫分了很多很多的房間,Schema就是其中的房間,一個Schema代表一個房間。 Table可以看作是每個Schema中的床,Table(床)就被放入每個 ...
  • 一、emp表 二、練習 1. 查詢出部門編號為30的所有員工2. 所有銷售員的姓名、編號和部門編號。3. 找出獎金高於工資的員工。4. 找出獎金高於工資60%的員工。5. 找出部門編號為10中所有經理,和部門編號為20中所有銷售員的詳細資料。 6. 找出部門編號為10中所有經理,部門編號為20中所有 ...
  • man 查看命令幫助,命令的詞典,更複雜的還有info,但不常用。 help 查看Linux內置命令的幫助,比如cd命令。 文件和目錄操作命令(18個) ls 全拼list,功能是列出目錄的內容及其內容屬性信息。 cd 全拼change directory,功能是從當前工作目錄切換到指定的工作目錄。 ...
  • 原文:http://blog.csdn.net/code_better/article/details/54898098 ...
  • 第1章 虛擬機安裝 1.1 鏡像下載 1.1.1 新版本下載 http://mirrors.aliyun.com #阿裡雲官方鏡像站點 1.1.2 舊版本下載 http://vault.centos.org/ #vault 電子倉庫 儘量使用種子文件下載,速度較快 1.2 VMware新建虛擬機 1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...