處理 Linux 信號:進程控制與異常管理的核心

個人主頁:chian-ocean

文章專欄-Linux

前言:

在 Linux 操作系統中,信號是用于進程間通信的一種機制,能夠向進程發送通知,指示某些事件的發生。信號通常由操作系統內核、硬件中斷或其他進程發送。接收和處理信號是 Linux 系統中進程控制和資源管理的一個重要組成部分。

在這里插入圖片描述

信號的保存

信號遞送(Delivery)

  • 信號的處理動作稱為信號遞送(Delivery)
    • 這意味著在 Linux 系統中,當信號發生時,它會被傳遞到目標進程并執行相應的操作。遞送是信號處理的第一步,是信號機制中至關重要的一部分。

2. 信號未決(Pending)

  • 信號從產生到遞送之間的狀態,稱為信號未決(Pending)。

    • 當信號發送到一個進程,但該進程因某些原因(如信號被屏蔽或進程正在執行其他操作)暫時無法處理信號時,這個信號就會處于未決狀態,等待后續處理。
  • Linux內核是通過一個一個位圖編標記信號,進而儲存信號

在這里插入圖片描述

  • block 位圖(通常是一個 sigset_t 類型的數據結構)用于記錄當前進程被阻塞的信號。每一位代表一個特定的信號,當該位被設置為1時,表示該信號處于被阻塞狀態;如果該位是0,則表示該信號未被阻塞,可以遞送給進程。
  • pending 位圖(Pending Bitmap)用于記錄進程中待處理的信號。位圖是一個位數組,其中每個比特代表一個信號的狀態(是否待處理)。
  • headler代表的是該信號所需要用的方法。

sigset_t

在這里插入圖片描述

定義:

sigset_t 是一個適用于信號管理的基本數據類型,通常在頭文件 <signal.h> 中定義。它的具體實現依賴于系統,但通常是一個位圖或位集合,每一位表示一個信號的狀態(是否被屏蔽、是否待處理等)。

sigset_t 的用途

  • 信號屏蔽:用于設置進程的信號掩碼(signal mask),即哪些信號被屏蔽,不允許遞送。例如,通過 sigprocmask 函數修改信號掩碼。
  • 信號檢查:通過 sigpending() 函數檢查進程是否有待處理的信號。
  • 信號操作:例如,sigaddset()sigdelset() 等函數可以用來向信號集添加或移除特定信號

常用函數與 sigset_t 的操作

在 Linux 系統中,sigset_t 是一個數據類型,用于表示信號集,通常用于管理信號的掩碼。它用于存儲一個進程中多個信號的集合,可以用來表示進程阻塞的信號、待處理的信號等。

sigset_t 類型定義

sigset_t 是一個適用于信號管理的基本數據類型,通常在頭文件 <signal.h> 中定義。它的具體實現依賴于系統,但通常是一個位圖或位集合,每一位表示一個信號的狀態(是否被屏蔽、是否待處理等)。

sigset_t 的用途

sigset_t 主要用于以下幾個方面:

  • 信號屏蔽:用于設置進程的信號掩碼(signal mask),即哪些信號被屏蔽,不允許遞送。例如,通過 sigprocmask 函數修改信號掩碼。
  • 信號檢查:通過 sigpending() 函數檢查進程是否有待處理的信號。
  • 信號操作:例如,sigaddset()sigdelset() 等函數可以用來向信號集添加或移除特定信號。

sigset_t 的操作

以下是一些與 sigset_t 相關的常見操作函數:

  • sigemptyset(sigset_t ,*set): 初始化一個空的信號集(即不包含任何信號)。

    sigset_t set;
    sigemptyset(&set); // 將 set 設為空信號集
    
  • sigfillset(sigset_t ,*set): 初始化一個包含所有信號的信號集。

    sigset_t set;
    sigfillset(&set); // 將 set 設為包含所有信號的信號集
    
  • sigaddset(sigset_t ,*set, int signo): 將指定的信號添加到信號集。

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT); // 將 SIGINT 添加到 set 中
    
  • sigdelset(sigset_t ,*set, int signo): 從信號集移除指定的信號。

    sigdelset(&set, SIGINT); // 從 set 中刪除 SIGINT
    
  • sigismember(const sigset_t ,*set, int signo): 檢查指定的信號是否在信號集中。

    if (sigismember(&set, SIGINT)) {// 如果 SIGINT 在 set 集合中
    }
    

控制sigset_t常見函數

sigprocmask(int how, const sigset_t ,*set, sigset_t ,*oldset): 修改進程的信號掩碼(即屏蔽哪些信號)。

  • sigismember(const sigset_t ,*set, int signo): 檢查指定的信號是否在信號集中。

    if (sigismember(&set, SIGINT)) {// 如果 SIGINT 在 set 集合中
    }
    
    • how:

      參數控制信號掩碼的設置方式:

      • SIG_BLOCK:把 set中的信號添加到 blocked(blocked= blocked | set)
      • SIG_UNBLOCK:從 blocked中刪除 set中的信號(blocked= blocked & set)
      • SIG_SETMASKblock= set
    sigset_t set, oldset;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigprocmask(SIG_BLOCK, &set, &oldset); // 阻塞 SIGINT
    
  • sigpending(sigset_t g*set): 獲取當前進程的未決信號集,返回一個信號集,表示所有尚未被處理的信號。

    sigset_t set;
    sigpending(&set); // 獲取當前進程的待處理信號
    

屏蔽字的實例

#include <iostream>
#include <signal.h>
#include <unistd.h>// 函數:用于打印信號集中的信號狀態
void pendingprint(sigset_t &pending)
{// 遍歷信號集中的每個信號,從31到1(Linux支持的信號范圍通常是1到31)for(int i = 31; i >= 1; i--){// 檢查信號集pending中是否包含第i個信號if (sigismember(&pending, i)){std::cout << "1";  // 如果信號存在,打印"1"}else{std::cout << "0";  // 如果信號不存在,打印"0"}}std::cout << "\n";  // 換行打印結果
}int main()
{// 定義信號集,用于保存信號掩碼、舊掩碼和待處理信號集sigset_t mask, old_mask;sigset_t pending;// 初始化信號集mask為空信號集sigemptyset(&mask);// 將SIGINT信號(Ctrl+C觸發的中斷信號)添加到信號集mask中sigaddset(&mask, SIGINT);// 將SIGINT信號添加到當前進程的信號掩碼中,即阻塞SIGINT信號// 并保存原來的信號掩碼到old_mask中sigprocmask(SIG_BLOCK, &mask, &old_mask);int cnt = 0;while(true){// 獲取當前進程的待處理信號集,并保存在pending中sigpending(&pending);// 調用pendingprint函數,打印待處理信號集中的信號pendingprint(pending);// 每次睡眠1秒鐘sleep(1);// 計數器,每次增加1if(++cnt == 5){// 在第20次循環時,解除阻塞SIGINT信號std::cout << "SIGINT UNLOCK" << std::endl;// 恢復之前的信號掩碼,即解除對SIGINT信號的阻塞sigprocmask(SIG_SETMASK, &old_mask, NULL);}}std::cout << "QUIT..." << std::endl;return 0;
}
  • 代碼中我會每秒打印penging中的數據
  • 第三秒中的時候,像進程發送2好信號,penging中會顯示為處理的信號,在bolck中該信號被阻塞,也就是被屏蔽。
  • 代碼執行第五秒中的時候,進程阻塞信號解除,由于penging中有未處理的信號,就會執行2好號信號。

在這里插入圖片描述

信號的捕捉

信號捕捉的時機

  1. 進程是否正在執行系統調用。
  2. 進程是否在空閑狀態(如調用 sleep())。
  3. 信號是否被發送。
  4. 信號是否被阻塞或保留直到適當時機。
  5. 信號是否導致進程退出或崩潰時處理。

信號執行的流程

在這里插入圖片描述

  • 用戶模式:進程在用戶模式下執行,直到某個信號因中斷、異常或系統調用被觸發。
  • 內核模式:當信號被觸發時,操作系統切換到內核模式,進行信號的處理。內核會完成信號的處理并準備將進程返回到用戶模式之前的狀態。
  • 信號處理:在信號處理過程中,內核會調用信號處理函數(如 do_signal())。如果信號需要對用戶指定的特定處理,系統會在信號處理時調用相應的函數。
  • 處理返回:信號處理函數執行完畢后,操作系統會通過 sigreturn 系統調用返回到用戶模式。
  • 恢復執行:操作系統恢復用戶模式下的程序執行,從中斷的地方繼續執行。

用戶態和內核態的切換

用戶態到內核態

  • 觸發方式:通過系統調用(如read(), write())或硬件中斷(如鍵盤中斷)。
  • 過程:
    • 當用戶程序調用系統調用時,會執行一個軟中斷(例如x86的int 0x80指令)。
    • 內核會保存當前用戶程序的上下文(如程序計數器、堆棧指針等),并設置內核模式。
    • 進入內核代碼執行,執行完后,準備返回用戶態。

內核態到用戶態

  • 觸發方式:內核任務完成后,需要返回用戶程序繼續執行。
  • 過程:
    • 內核將處理結果返回用戶進程,并恢復用戶進程的上下文。
    • 恢復用戶態的堆棧指針、程序計數器等寄存器,并將程序從內核模式切換回用戶模式。
    • 繼續執行用戶進程。

sigaction

  • sigaction是處理粒度更加強大的一個系統調用。

在這里插入圖片描述

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
參數:
  • signum:指定信號的編號(例如,SIGINTSIGTERM 等)。
  • act:指向 struct sigaction 結構體的指針,用于指定新的信號處理程序及其設置。
  • oldact:指向 struct sigaction 結構體的指針,用于保存之前的信號處理程序(可選)。如果不關心舊的處理程序,可以傳遞 NULL
返回值:
  • 成功時,返回 0
  • 失敗時,返回 -1 并設置 errno
struct sigaction {void (*sa_handler)(int);   // 信號處理函數void (*sa_sigaction)(int, siginfo_t *, void *);  // 備用信號處理函數sigset_t sa_mask;           // 用于指定在信號處理期間要阻塞的信號int sa_flags;               // 信號處理行為的標志void (*sa_restorer)(void);  // 不常用,保留字段
};

代碼示例:

#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
#include<cstdlib>// 信號處理函數,當捕獲到信號時執行
void headler(int signo)
{// 輸出捕獲到的信號類型std::cout << "catch signal --- signo :" << signo << std::endl;sleep(4);// 退出程序,返回 1 作為退出狀態exit(1);
}int main()
{   // 定義 sigaction 結構體,用于設置新的信號處理行為 (sa) 和保存舊的信號處理行為 (osa)struct sigaction sa, osa;// 使用 memset 將結構體清零,確保結構體中的字段沒有未初始化的值memset(&sa, 0, sizeof(sa));memset(&osa, 0, sizeof(osa));// 清空信號集,準備設置信號屏蔽sigemptyset(&sa.sa_mask);// 將 SIGINT 信號添加到屏蔽信號集中,意思是處理 SIGINT 時,其他信號會被阻塞sigaddset(&sa.sa_mask, SIGINT);// 設置自定義的信號處理函數,當 SIGINT 信號觸發時,調用 headler 函數sa.sa_handler = headler;// 注冊信號處理函數,綁定 SIGINT 信號與信號處理函數 headler,同時保存原來的信號處理方式sigaction(SIGINT, &sa, &osa);// 進入一個無限循環,模擬進程運行while (true){// 輸出當前進程的 pid,表示進程正在運行std::cout << "Process Running ...: pid: " << getpid() << std::endl;// 每 1 秒輸出一次,模擬進程持續運行sleep(1);}return 0;
}

信號處理函數 headler

  • 該函數定義了如何處理接收到的 SIGINT 信號。當捕獲到 SIGINT 信號時,會輸出信號編號,然后模擬處理過程(休眠 4秒),最后退出程序并返回狀態碼 1。

信號處理結構體 sigaction

  • sigaction 是用來定義和控制信號處理方式的結構體。通過它可以設置信號的處理函數、信號掩碼等信息。
  • 通過 memset 清空結構體,確保沒有未初始化的字段。
  • 使用 sigemptysetsigaddset 配置信號屏蔽集,指定在處理 SIGINT 時,阻塞其他信號(在本例中,僅阻塞 SIGINT 自身)。

sigaction 調用

  • sigaction(SIGINT, &sa, &osa) 設置 SIGINT 信號的處理程序為 headler,并保存原來的信號處理方式(雖然在這里我們沒有使用 osa 來恢復原處理方式)。

進程運行

  • 進入無限循環 while(true),打印當前進程的 pid(進程 ID),模擬一個長時間運行的進程。
  • 每秒輸出一次進程信息,并通過 sleep(1) 使程序每秒鐘暫停一次。

信號捕獲時期的相關問題

  • 信號遞歸:信號處理期間默認屏蔽當前信號,避免遞歸調用。
void headler(int signo)
{int cnt  = 20;while(cnt --){std::cout << "catch signal --- signo :" << signo <<std:: endl;sleep(1);}exit(1);
}
  1. 在這里面headler方法進行循環,并且休眠一秒,在此期間持續像進發送2號信號。

在這里插入圖片描述

  1. 同時可以及逆行進行多信號屏蔽。
sigaddset(&sa.sa_mask,1);
sigaddset(&sa.sa_mask,3);
sigaddset(&sa.sa_mask,4);

在這里插入圖片描述

  • 信號丟失:如果信號未及時處理,可能丟失,尤其是長時間阻塞時。
  • 系統調用中斷:信號可能中斷系統調用,導致 EINTR 錯誤。
  • 信號屏蔽問題:如果未正確設置信號掩碼,可能導致信號被過多屏蔽或錯誤處理。

信號pending表的處理時機

  • 信號在調用處理方法之前會被制空
#include<iostream>
#include<signal.h>
#include<unistd.h>
#include<cstring>
#include<cstdlib>// 聲明一個全局的 sigset_t 變量,用于保存掛起的信號
sigset_t pending;// 打印掛起信號的狀態(1表示掛起,0表示沒有掛起)
void PrintPending()
{sigset_t set;sigpending(&set);  // 獲取當前掛起的信號集合// 遍歷信號編號,打印每個信號的狀態for (int signo = 31; signo >= 1; signo--){if (sigismember(&set, signo))  // 檢查該信號是否在掛起集合中std::cout << "1";  // 如果掛起,打印 1elsestd::cout << "0";  // 如果沒有掛起,打印 0}std::cout << "\n";  // 輸出換行
}// 信號處理程序
void headler(int signo)
{int cnt = 5;  // 設置循環次數為 5while (cnt--)  // 每次處理信號時,循環 5 次{PrintPending();  // 打印當前掛起的信號狀態sleep(1);  // 休眠 1 秒,模擬信號處理的過程std::cout << "catch signal --- signo :" << signo << std::endl;  // 輸出捕獲到的信號編號}exit(1);  // 信號處理完畢后退出程序
}int main()
{signal(SIGINT, headler);  // 設置 SIGINT 信號的處理函數為 headlersigset_t mask, old_mask;sigemptyset(&mask);  // 初始化信號集 mask,清空所有信號sigaddset(&mask, SIGINT);  // 將 SIGINT 信號加入到 mask 中,表示屏蔽 SIGINT 信號sigprocmask(SIG_BLOCK, &mask, &old_mask);  // 阻塞 SIGINT 信號,并保存原信號掩碼到 old_maskint cnt = 1;while (true){sigpending(&pending);  // 獲取當前掛起的信號PrintPending();  // 打印掛起信號的狀態sleep(1);  // 程序每秒輸出一次狀態cnt++;  // 計數器加 1std::cout << "Process Running ...: pid: " << getpid() << std::endl;  // 輸出當前進程的 PIDif (cnt % 5 == 0)  // 每經過 5 次循環{PrintPending();  // 再次打印掛起信號的狀態sleep(1);  // 休眠 1 秒std::cout << "SIGINT UNLOCK" << std::endl;  // 輸出解鎖 SIGINT 信號的提示sigprocmask(SIG_SETMASK, &old_mask, NULL);  // 恢復原來的信號掩碼,解除對 SIGINT 的阻塞}}std::cout << "QUIT..." << std::endl;  // 輸出退出提示return 0;
}
  • 程序啟動后,會阻塞 SIGINT 信號。
  • 每秒鐘,程序打印當前進程的 PID 和掛起的信號狀態。
  • 每經過 5 次循環,解除對 SIGINT 信號的阻塞,允許信號被捕獲并處理。
  • 捕獲到 SIGINT 信號后,headler 會打印掛起信號狀態,處理信號并退出。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73835.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73835.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73835.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

通信協議之串口

文章目錄 簡介電平標準串口參數及時序USART與UART過程引腳配置 簡介 點對點&#xff0c;只能兩設備通信只需單向的數據傳輸時&#xff0c;可以只接一根通信線當電平標準不一致時&#xff0c;需要加電平轉換芯片&#xff08;一般從控制器出來的是信號是TTL電平&#xff09;地位…

Unity編輯器功能及拓展(1) —特殊的Editor文件夾

Unity中的Editor文件夾是一個具有特殊用途的目錄&#xff0c;主要用于存放與編輯器擴展功能相關的腳本和資源。 一.糾纏不清的UnityEditor 我們Unity中進行游戲構建時&#xff0c;我們經常遇到關于UnityEditor相關命名空間丟失的報錯&#xff0c;這時候&#xff0c;只得將報錯…

工具類-csv文件導入數據庫思路

首先&#xff0c;讓我們來看下數據庫建表語句&#xff1a; CREATE TABLE behavior_reports (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 報告ID,report_type VARCHAR(50) NOT NULL COMMENT 報告類型(daily, weekly, monthly),start_date DATE NOT NULL COMMENT 開始日期,e…

軟件工程之軟件開發模型(瀑布、迭代、敏捷、DevOps)

1. 瀑布模型&#xff08;Waterfall Model&#xff09; 定義與流程 瀑布模型是線性順序的開發流程&#xff0c;包含需求分析、設計、編碼、測試、維護等階段&#xff0c;每個階段完成后才能進入下一階段&#xff0c;類似“瀑布流水”逐級推進。 核心特點 嚴格階段劃分&#…

FreeRTOS與RT-Thread內存分配對比分析

一、動態內存分配策略 ?FreeRTOS ?分配算法多樣性&#xff1a;提供5種動態內存管理算法&#xff08;heap_1至heap_5&#xff09;&#xff0c;覆蓋從簡單到復雜的場景。例如&#xff1a; heap_1&#xff1a;僅支持分配不支持釋放&#xff0c;適用于固定任務棧分配。heap_4&…

202519 | Mybatis-Plus

快速入門 MyBatis-Plus&#xff08;簡稱 MP&#xff09;是 MyBatis 的增強工具&#xff0c;它在 MyBatis 的基礎上只做增強不做改變&#xff0c;簡化了開發&#xff0c;提高了效率。以下是 MyBatis-Plus 的快速入門指南&#xff0c;幫助您快速上手使用。 1. 環境準備 JDK&…

Linux C語言調用第三方庫,第三方庫如何編譯安裝

在 Linux 環境下使用 C 語言調用第三方庫時&#xff0c;通常需要先對第三方庫進行編譯和安裝。以下為你詳細介紹一般的編譯安裝步驟&#xff0c;并給出不同類型第三方庫&#xff08;如使用 Makefile、CMake 構建系統&#xff09;的具體示例。 一般步驟 1. 獲取第三方庫源碼 …

linux基本命令(1)--linux下的打包命令 -- tar 和gzip

tar 解壓 &#xff0c;打包 語法&#xff1a;tar [主選項輔選項] 文件或者目錄 使用該命令時&#xff0c;主選項是必須要有的&#xff0c;它告訴tar要做什么事情&#xff0c;輔選項是輔助使用的&#xff0c;可以選用。 主選項&#xff1a; c 創建新的檔案文件。如果用戶想備…

Python 序列構成的數組(對序列使用+和_)

對序列使用和* Python 程序員會默認序列是支持 和 * 操作的。通常 號兩側的序列由 相同類型的數據所構成&#xff0c;在拼接的過程中&#xff0c;兩個被操作的序列都不會被 修改&#xff0c;Python 會新建一個包含同樣類型數據的序列來作為拼接的結果。 如果想要把一個序列…

[ C語言 ] | 從0到1?

目錄 認識計算機語言 C語言 工欲善其事必先利其器 第一個C語言代碼 這一些列 [ C語言 ] &#xff0c;就來分享一下 C語言 相關的知識點~ 認識計算機語言 我們說到計算機語言&#xff0c;語言&#xff0c;就是用來溝通的工具&#xff0c;計算機語言呢&#xff1f;就是我們…

【通道注意力機制】【SENet】Squeeze-and-Excitation Networks

0.論文摘要 卷積神經網絡建立在卷積操作的基礎上&#xff0c;通過融合局部感受野內的空間和通道信息來提取有意義的特征。為了增強網絡的表示能力&#xff0c;最近的一些方法展示了增強空間編碼的好處。在本研究中&#xff0c;我們專注于通道關系&#xff0c;并提出了一種新穎…

kubernetes Calico(CNI) NetworkPolicy 流量管理 設置networkpolicy 策略 下集

1、kubernetes 網絡策略&#xff08;網絡隔離策略&#xff09; Network Policy 是 Kubernetes 中用于控制 Pod 之間網絡通信的一種機制。它通過定義規則&#xff0c;限制哪些 Pod 或外部實體可以與目標 Pod 通信&#xff08;基于標簽、命名空間、端口等&#xff09;。Network …

sqlmap基礎命令總結

?注意事項:僅用于授權測試&#xff0c;避免非法使用。 目錄 ?一、基礎命令 ?二、數據庫信息獲取 ?三、繞過 WAF/IDS ?四、文件系統與系統命令 ?五、高級功能與優化 ?六、實戰示例 ?一、基礎命令 ?檢測注入點 sqlmap -u "http://target.com/index.php?id1&…

Unity光線傳播體積(LPV)技術實現詳解

一、LPV技術概述 光線傳播體積(Light Propagation Volumes)是一種實時全局光照技術&#xff0c;通過將場景中的間接光信息存儲在3D網格中&#xff0c;實現動態物體的間接光照效果。 核心優勢&#xff1a; 實時性能&#xff1a;相比傳統光照貼圖&#xff0c;支持動態場景 硬件…

SpringBoot (一) 自動配置原理

目錄 一 自動配置 1:數據源的手動配置 1:SpringBoot的自動配置 二 自動配置的完整流程&#xff1a;&#xff08;底層&#xff09; 1. 場景化依賴與Starter機制 2. 主程序入口與注解驅動 3. 自動配置類的加載與篩選 4. 自動配置類的實現邏輯 5. 自動配置的觸發與執行流…

OJ題:移動零

雙指針法 c 語言實現 void moveZeroes(int* nums, int numsSize) {int dest,cur; //創建臨時指針和目標指針destcur0;//出初始化while(cur<numsSize)//遍歷{if(nums[cur]!0){swap(&nums[cur],&nums[dest]);cur;dest;}else{cur;}}} 思路是建立兩個指針&#xff0…

pycharm終端操作遠程服務器

pycharm項目已經連接了遠程服務器&#xff0c;但是打開終端&#xff0c;卻依舊顯示的是本地的那個環境&#xff0c;也就是說沒有操作遠程的那個環境。只能再使用Xshell去操作遠程環境&#xff0c;很麻煩&#xff0c;找了下教程。 來源&#xff1a;https://blog.csdn.net/maolim…

(頭歌作業—python)3.2 個人所得稅計算器(project)

第1關&#xff1a;個人所得稅計算器 任務描述 本關任務&#xff1a;編寫一個個人所得稅計算器的小程序。 相關知識 個人所得稅繳納標準 2018 年 10 月 1 日以前&#xff0c;個稅免征額為 3500 元/月&#xff0c;調整后&#xff0c;個稅免征額為 5000 元/月&#xff0c; 7 級超…

Redis場景問題1:緩存穿透

Redis 緩存穿透是指在緩存系統&#xff08;如 Redis&#xff09;中&#xff0c;當客戶端請求的數據既不在緩存中&#xff0c;也不在數據庫中時&#xff0c;每次請求都會直接穿透緩存訪問數據庫&#xff0c;從而給數據庫帶來巨大壓力&#xff0c;甚至可能導致數據庫崩潰。下面為…

CUDA Memory Fence 函數的功能與硬件實現細節

CUDA Memory Fence 函數的功能與硬件實現細節 Memory Fence 的基本功能 CUDA中的memory fence函數用于控制內存操作的可見性順序&#xff0c;確保在fence之前的內存操作對特定范圍內的線程可見。主要功能包括&#xff1a; 排序內存操作&#xff1a;確保fence之前的內存操作在…