驅動開發學習筆記---併發與競爭

来源:https://www.cnblogs.com/zhuzi1/archive/2022/11/27/16930729.html
-Advertisement-
Play Games

一、併發與競爭簡介 併發:多個“用戶”同時訪問一個共用的記憶體。 競爭:多個“用戶”同時訪問一段共用的記憶體並對其修改,就會造成數據混亂,甚至程式崩潰,這就是競爭。 二、造成併發與競爭的原因 1、多線程併發訪問, Linux 是多任務(線程)的系統,所以多線程訪問是最基本的原因。 2、搶占式併發訪問, ...


一、併發與競爭簡介

併發:多個“用戶”同時訪問一個共用的記憶體。

競爭:多個“用戶”同時訪問一段共用的記憶體並對其修改,就會造成數據混亂,甚至程式崩潰,這就是競爭。

二、造成併發與競爭的原因

1、多線程併發訪問, Linux 是多任務(線程)的系統,所以多線程訪問是最基本的原因。

2、搶占式併發訪問, Linux 內核支持搶占,也就是說調度程式可以在任意時刻搶占正在運行的線程,從而運行其他的線程。

3、中斷程式併發訪問,這個無需多說,學過 STM32 的同學應該知道,硬體中斷的權利可是很大的。

4、 SMP(多核)核間併發訪問,現在 ARM 架構的多核 SOC 很常見,多核 CPU 存在核間併發訪問。

三、臨界區(共用資源

在多任務的工作模式下有多個執行單位,它們通常可以擁有一段共用空間(比如全局變數、共用記憶體等等)。所以要對共用資源進行保護,某個線程局部變數不需要保護,要保護的是多個線程都會訪問的共用數據。如:全局變數,設備結構體成員

四、避免併發與競爭的操作:

1、原子操作

原子操作就是指不能再進一步分割的操作,一般原子操作用於變數或者位操作。

對於基本的賦值操作比如a=1;在內核裡面的步驟為:

ldr r0, =0X30000000         // 變數 a 地址 
ldr r1, = 3                 // 要寫入的值 
str r1, [r0]                // 將 3 寫入到 a 變數中 

因為一個簡單的賦值就有三條語句,然後在多進程裡面就可以能出現競爭現象

image-20221127205312878

在編寫驅動時,對全局變數要求保證原子操作可以用 atomic_t 結構體:

typedef struct {
int counter;
} atomic_t;

通過原子整形API庫函數進行整形操作和位操作。

2、自旋鎖

原子操作可以用來解決變數訪問的問題,我們在實際應用中有時候需要操作的不止是變數,還有一塊區域(比如結構體變數)等。為了保護他們,我們就添加了各種鎖,比如自旋鎖。自旋鎖適用於短時期輕量級加鎖,長時間就用信號量。

自旋鎖使用註意事項:

  1. 因為等待資源的線程會一直“自旋”,所以線程持有自旋鎖,訪問臨界區的時間不能太長。

  2. 臨界區中,不能存在任何會引起線程阻塞、睡眠的操作,否者可能引起死鎖。

  3. 不能遞歸的申請自旋鎖。

  4. 考慮到程式的可移植性,在使用自旋鎖時不管你的cpu是單核,還是多核,都當做多核來使用。

死鎖:線程在獲取鎖之後阻塞或睡眠,導致多個線程都阻塞。

自旋鎖會自動禁止搶占,也就說當線程 A得到鎖以後會暫時禁止內核搶占。如果線程 A 在持有鎖期間進入了休眠狀態,那麼線程 A 會自動放棄 CPU 使用權。線程 B 開始運行,線程 B 也想要獲取鎖,但是此時鎖被 A 線程持有,而且內核搶占還被禁止了!線程 B 無法被調度出去,那麼線程 A 就無法運行,鎖也就無法釋放,好了,死鎖發生了!

3.信號量

在這裡插入圖片描述

信號量特點:

1.線程可以訪問的臨界區比較大,訪問資源的時間長,所以臨界區中可以調用引起阻塞的操作。 2.等待資源的線程不會一直等待,會讓出 cpu 使用權,進入掛起、睡眠狀態。(cpu經過調度執行其它線程) 3.正是因為會進入睡眠態,所以不能在中斷中使用,同時也不能在自旋鎖的臨界區中使用。(中斷講究快進快出) 4.在等待資源時CPU 會經歷 切換、喚醒進程等等操作,會產生一定的開銷。當使用信號量所爭取的利益大於這個開銷時就不要使用信號量。

4.互斥體

信號量值 = 1 可以實現互斥訪問,Linux 比信號量更專業的機制來進行互斥,即互斥體 mutex。使用過程中有其它線程想要獲取該資源的鎖,那麼它就會被阻塞陷入睡眠狀態,直到該資源被解鎖才會被喚醒。

互斥體特點: 1.mutex 可以導致休眠,因此也不能在中斷中使用 mutex,中斷中只能使用自旋鎖。 2.和信號量一樣, mutex 保護的臨界區可以調用引起阻塞的 API 函數。(臨界區中可以引起塞) 3.因為一次只有一個線程可以持有 mutex,因此,必須由 mutex 的持有者釋放 mutex。並且 mutex 不能遞歸上鎖和解鎖。

互斥體使用註意事項: 互斥體和自旋鎖都是解決互斥問題的一種手段。互斥體是進程級別的,互斥體在使用的時候會發生進程間的切換,因此,使用互斥體資源開銷比較大。自旋鎖可以節省上下文切換的時間,如果持有鎖的時間不長,使用自旋鎖是比較好的選擇,如果持有鎖時間比較長,互斥體顯然是更好的選擇。

互斥體與自旋鎖區別: 1.當鎖不能被獲取到時,使用互斥體的開銷是進程上下文切換時間,使用自旋鎖的開銷是等待獲取自旋鎖(由臨界區執行時間決定)。若臨界區比較小,宜使用自旋鎖,若臨界區很大,應使用互斥 體。 2.互斥體所保護的臨界區可包含可能引起阻塞的代碼,而自旋鎖則絕對要避免用來保護包含這樣代碼的臨界區。因為阻塞意味著要進行進程的切換,如果進程被切換岀去後,另一個進程企圖獲取本自旋鎖,死鎖就會發生。 3.互斥體存在於進程上下文。因此,如果被保護的共用資源需要在中斷或軟中斷情況下使用,則在互斥體和自旋鎖之間只能選擇自旋鎖。當然,如果一定要使用互斥體,則只能通過mutextrylock()方式進行,不能獲取就立即返回以避免阻塞。

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

-Advertisement-
Play Games
更多相關文章
  • 前言 本篇是c++總結的第二篇,關於c++的對象模型,在構造、拷貝虛函數上重點分析,也包含了c++11class的新用法和特性,如有不當,還請指教! c++三大特性 訪問許可權 ​ 在c++中通過public、protected、private三個關鍵字來控製成員變數和成員函數的訪問許可權,它們分別表示 ...
  • Spring 框架可以為 Java 應用程式開發提供全面的基礎設施支持,它是現在非常流行的 Java 開源框架,對於一個 Java 開發人員來說,熟練掌握 Spring 是必不可少的。 ...
  • 1. 查看Linux伺服器版本信息 # cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) 2. 禪道開源版安裝包下載 wget http://dl.cnezsoft.com/zentao/9.8.2/ZenTaoPMS.9.8. ...
  • 目錄 一.OpenGL 色階 1.Windows OpenGL ES 版本 2.Windows OpenGL 版本 二.OpenGL 色階 GLSL Shader 三.猜你喜歡 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 Ope ...
  • 我們都知道在Java編程中多線程的同步使用synchronized關鍵字來標識,那麼這個關鍵字在JVM底層到底是如何實現的呢。 我們先來思考一下如果我們自己實現的一個鎖該怎麼做呢: 首先肯定要有個標記記錄對象是否已經上鎖,執行同步代碼之前判斷這個標誌,如果對象已經上鎖線程就阻塞等待鎖的釋放。 其次要 ...
  • JZ7重建二叉樹 描述 給定節點數為 n 的二叉樹的前序遍歷和中序遍歷結果,請重建出該二叉樹並返回它的頭結點。 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6} 提示: 1.vin.length == pre.length 2.pre 和 vin ...
  • 本文是對Datawhale的動手學數據分析課程的學習總結,記錄了整體的學習過程、答案以及個人感想,代碼較為詳細。 ...
  • 簡介 本文的初衷是希望幫助那些有其它平臺視覺演算法開發經驗的人能快速轉入Halcon平臺下,通過文中的示例開發者能快速瞭解一個Halcon項目開發的基本步驟,讓開發者能把精力完全集中到演算法的開發上面。 首先,你需要安裝Halcon,HALCON 18.11.0.1的安裝包會放在文章末尾。安裝包分開發和 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...