原子性操作原理分析

来源:https://www.cnblogs.com/jiau/archive/2020/06/24/13189253.html
-Advertisement-
Play Games

1. 概念 原子操作是指不被打斷的操作,即它是最小的執行單位。最簡單的原子操作就是一條條的彙編指令(不包括一些偽指令,偽指令會被彙編器解釋成多條彙編指令)。在 linux 中原子操作對應的數據結構為 atomic_t,定義如下: typedef struct { int counter; } ato ...


1. 概念

原子操作是指不被打斷的操作,即它是最小的執行單位。最簡單的原子操作就是一條條的彙編指令(不包括一些偽指令,偽指令會被彙編器解釋成多條彙編指令)。在 linux 中原子操作對應的數據結構為 atomic_t,定義如下:

typedef struct {
	int counter;
} atomic_t;

本質上就是一個整型變數,之所以定義這麼一個數據類型,是為了讓原子操作函數只接受 atomic_t 類型的操作數,如果傳入的不是 atomic_t 類型數據,在程式編譯階段就不會通過;另一個原因就是確保編譯器不會對相應的值進行訪問優化,確保對它的訪問都是對記憶體的訪問,而不是對寄存器的訪問。

2. 賦值操作

ARM 處理器有直接對記憶體地址進行賦值的指令(STR)。

#define atomic_set(v,i)	(((v)->counter) = (i))

3. 讀操作

用 volatile 來防止編譯器對變數訪問的優化,確保是對記憶體的訪問,而不是對寄存器的訪問。

#define atomic_read(v)	(*(volatile int *)&(v)->counter)

4. 加操作

使用獨占指令完成累加操作。

static inline void atomic_add(int i, atomic_t *v)
{
	unsigned long tmp;
	int result;
	// 使用獨占指令讀取,然後執行加操作,獨占寫失敗時就重新執行
	__asm__ __volatile__("@ atomic_add\n"
"1:	ldrex	%0, [%3]\n"
"	add	%0, %0, %4\n"
"	strex	%1, %0, [%3]\n"
"	teq	%1, #0\n"
"	bne	1b"
	: "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
	: "r" (&v->counter), "Ir" (i)
	: "cc");
}

5. 減操作

對比加操作減操作的代碼可以看出,它們非常的相似,其實不同的地方就一句,所以現在最新的內核源碼中已經使用巨集定義 ATOMIC_OP(op, c_op, asm_op) 來重寫了這部分代碼。

static inline void atomic_sub(int i, atomic_t *v)
{
	unsigned long tmp;
	int result;
	// 使用獨占指令讀取,然後執行減操作,獨占寫失敗時就重新執行
	__asm__ __volatile__("@ atomic_sub\n"
"1:	ldrex	%0, [%3]\n"
"	sub	%0, %0, %4\n"
"	strex	%1, %0, [%3]\n"
"	teq	%1, #0\n"
"	bne	1b"
	: "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
	: "r" (&v->counter), "Ir" (i)
	: "cc");
}

6. 其他操作

類似的原子操作函數還有一些,比如 atomic_XXX_return、atomic_cmpxchg、atomic_clear_mask,以及在此基礎上實現的 atomic_inc、atomic_dec、atomic_XXX_and_test、atomic_XXX_return等。以上代碼都是針對 SMP 處理器的實現方式,針對非 SMP 處理器,由於不存在其他核心的搶占,所以只需要防止其他進程搶占即可實現原子操作,例如加操作

static inline int atomic_sub_return(int i, atomic_t *v)
{
	unsigned long flags;
	int val;
	// 通過關閉中斷防止其他進程打斷代碼的執行
	raw_local_irq_save(flags);
	val = v->counter;
	v->counter = val -= i;
	// 恢復中斷原始的狀態
	raw_local_irq_restore(flags);

	return val;
}

7. 總結

原子性操作的實現需要具體體繫結構相關的指令集的支持。


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

-Advertisement-
Play Games
更多相關文章
  • //判斷後臺返回數據是否沒數據,沒數據DataGrid添加一行 $(this).datagrid('appendRow', { itemid: '<div style="text-align:center;color:red">沒有數據!</div>' }).datagrid('mergeCells ...
  • 前言 在2.2里程碑中我們增加了一些新的功能,正如標題所寫通過請求頭進行導出我們不同格式的文件.下麵我們來看一下如何使用.通過這種方式無論是對我們的數據多用途,還是說對我們的數據校驗都做到了輕鬆易配。 同時我們也將在本周發佈2.3版本,另外3.0版本我們將進行一次大的性能提升。3.0版本我們將對Ra ...
  • 我們利用IIS建立網站的時候,一般都是設定好網站名稱和物理地址,直接下一步建立完成了。正常訪問都沒問題,但如果我們這時候想要更改訪問的IP或者埠號,打開了很多設置項就是沒找到設置的地方。原來它一直在右邊的那個“連接”或者叫“綁定”那裡。 ...
  • 前言 RSA加密演算法是一種非對稱加密演算法,簡單來說,就是加密時使用一個鑰匙,解密時使用另一個鑰匙。 因為加密的鑰匙是公開的,所又稱公鑰,解密的鑰匙是不公開的,所以稱為私鑰。 密鑰 關於RSA加密有很多文章,但幾乎都只介紹了RSACryptoServiceProvider類的使用方法,如果只是走走看看 ...
  • 前言 上一篇【.Net Core微服務入門全紀錄(五)——Ocelot-API網關(下)】中已經完成了Ocelot + Consul的搭建,這一篇簡單說一下EventBus。 EventBus-事件匯流排 首先,什麼是事件匯流排呢? 貼一段引用: 事件匯流排是對觀察者(發佈-訂閱)模式的一種實現。它是一種 ...
  • 如果要支持Blazor WebAssembly的本地化,應該如何實現呢?下麵,我們就按照本地化問題操作中所涉及的所有主要問題以提問的方式進行說明。 1.本地化的核心原理是什麼? 答:就是顯式地在Program.Main方法中設置 CultureInfo.DefaultThreadCurrentCul ...
  • 大家好,我是良許。 在我們編寫代碼的時候,我們經常需要知道兩個文件之間,或者同一個文件不同版本之間有什麼差異性。在 Windows 下有個很強大的工具叫作 BeyondCompare ,那在 Linux 下需要用到什麼工具呢? 本文介紹 9 種 Linux 下常用的 9 種代碼比對工具,不僅有命令行 ...
  • 利用數組實現 1 #include<stdio.h> 2 #include<string.h> 3 4 void copy_string(char str1[],char str2[]) 5 { 6 int i = 0; 7 while(str2[i] != '\0') 8 { 9 str1[i] ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...