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

来源: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
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...