【轉譯】Linux中的信號(signal)

来源:https://www.cnblogs.com/jiaoran/archive/2022/04/23/linux-signals.html
-Advertisement-
Play Games

一篇科普文章,介紹什麼是 Linux 信號,以及它的基本用法,內含精美圖表。 ...


本文是一篇科普文章,介紹什麼是 Linux 信號,以及它的基本用法。原文鏈接見底部參考。


Common sources of Linux signals

Linux中有許多處於不同狀態的進程。這些進程屬於用戶應用程式或操作系統。我們需要一種機制讓內核和這些進程協調它們的活動。其中一種方式是在一個進程有重大改變時通知其他進程,因此我們有了 信號 的概念。

信號基本上是一種單向通知。信號可以由內核發送給一個進程,或由一個進程發送給另一個進程,或者一個進程發送給它自己。

Linux信號的概念來源於Unix。在後來的Linux版本中,加入了實時(real-time)信號。信號是一種簡單和輕量級的進程間通信形式,因此適用於嵌入式系統。

有關信號的討論

什麼是信號?

總共有 31 個標準信號,編號為 1-31。每個信號命名為“SIG”開頭,後跟一個尾碼(如INT、HUP、KILL等)。從 2.2 版開始,Linux 內核支持 33 種不同的實時信號,編號為 32-64,但應用程式應改為使用 SIGRTMIN + n 表示法。標準信號有特定用途,但 SIGUSR1 和 SIGUSR2 的使用可以由程式自定義。實時信號也可由程式定義。

0號信號,即 POSIX.1 標準中所說的null信號,一般不使用,但在 kill 函數中有個特殊的用途。使用時沒有信號被髮送,但可以用來(相當不可靠)檢查進程是否仍然存在。

Linux中的信號實現完全符合 POSIX 標準。最新的實現應該傾向於使用 sigaction 而不是傳統的信號介面。

正如硬體子系統可以中斷處理器一樣,信號可以中斷進程的執行。因此,它們被看作是軟體中斷。一般來說,中斷處理程式(interrupt handlers)處理硬體中斷,而信號處理程式(signal handlers)則處理信號導致的中斷。

通常信號被映射到特定的按鍵輸入,比如,SIGINT代表ctrl+c,SIGSTOP代表ctrl+z,SIGQUIT代表ctrl+\。

信號如何影響進程的狀態?

一些信號會終止正在接受信號的進程:SIGHUP、SIGINT、SIGTERM、SIGKILL。有一些信號不僅可以終止進程還會輸出一些內核信息,以幫助程式員調試出錯的地方,如SIGABRT(abort)、SIGBUS(bus error)、SIGILL(illegal instruction)、SIGSEGV(invalid memory reference無效記憶體引用)、SIGSYS(bad system call錯誤的系統調用) )。用於停止進程的信號有:SIGSTOP、SIGTSTP。 SIGCONT 是恢復已停止的進程。

一個程式可以覆蓋信號的預設行為。例如,一個互動式程式可以忽略SIGINT(由ctrl+c輸入產生)。不過有兩個例外需要註意,SIGKILL和SIGSTOP,它們不能被忽略、阻止或用這種方式覆蓋。

讓我們看一個父進程和其子進程的例子。假設子進程向自己發送了SIGSTOP,子進程將被停止。這反過來又會觸發SIGCHLD到父進程。然後,父進程可以使用SIGCONT向子進程發出繼續運行的信號。當子進程從停止狀態重新運行時,另一個SIGCHLD被髮送到父進程。如果後來,子進程退出了,最後的SIGCHLD會被髮送到父進程。

信號類似於異常(exception)嗎?

一些編程語言能夠使用諸如try-throw-catch這樣的結構進行異常處理。
但信號與異常並不類似。相反,失敗的系統或庫調用會返回非零的退出代碼。當一個進程被終止時,它的退出代碼是128加信號編號。例如,一個被SIGKILL殺死的進程將返回137(128+9)。

信號是同步還是非同步的?

信號既可以是同步,也可以是非同步。

同步信號的出現是由於指令導致了一個無法恢復的錯誤,如非法地址訪問。這些信號被髮送到導致它的線程。這些信號也被稱為陷阱(trap),因為它們也會導致陷阱進入內核的陷阱處理程式(trap handler)。

非同步信號是對當前執行環境的外部信號。從另一個進程中發送 SIGKILL 就是這樣一個例子。這些也被稱為軟體中斷。

信號的生命周期是什麼?

一個信號經歷三個階段:

  1. Generation:信號可以由內核或任何進程生成,生成後會將其發送給特定的進程。信號由其編號表示,沒有額外的數據或參數。因此,信號是輕量級的。但是,POSIX 實時信號傳遞額外的數據。可以生成信號的系統調用和函數包括 raise、kill、killpg、pthread_kill、tgkill 和 sigqueue。

  2. Delivery:信號在傳遞之前一直處於待處理狀態。通常,內核會儘快將信號傳遞給進程。但是,如果對應的進程阻塞了信號,它將保持未處理狀態直到解除阻塞。

  3. Processing:一旦信號被傳遞到,就會以多種方式中其中一種進行處理。每個信號都有一個預設的行為:忽略信號;或終止進程,有時使用核心轉儲(core dump);或停止/繼續該過程。對於非預設行為,對應的處理函數會被調用。通過 sigaction 函數指定究竟採用哪一種處理方式。

什麼是信號阻塞和解除阻塞?

信號打斷了程式執行的正常流程。當進程正在執行一些關鍵代碼或更新與信號處理程式共用的數據時,這是不希望看到的。阻斷的引入解決了這個問題。不過代價是,信號處理被延遲了。

每個進程都可以指定它是否要阻塞一個特定的信號。如果被阻斷,而信號確實發生了,操作系統將把該信號作為待處理信號。一旦進程解除阻斷,該信號將被傳遞。當前被屏蔽的信號集合被稱為信號屏蔽(signal mask)。

無限期地阻斷一個信號是沒有意義的。為了這個目的,進程可以在接受到信號後選擇忽略它,被一個進程屏蔽的信號不會影響其他進程,他們可以正常接收信號。

信號屏蔽(Signal mask)可以用 sigprocmask(單線程)或 pthread_sigmask(多線程)來設置。 當一個進程有多個線程時,信號可以針對每個線程分別設置是否屏蔽。信號將被傳遞給任何一個沒有阻斷它的線程。從本質上講,信號處理程式是針對某個進程的,信號掩碼是針對某個線程的。

一個進程可以有多個待處理的信號嗎?

是的,許多標準信號可以在進程中被掛起。然而,一個給定的信號類型只能有一個實例被掛起。這是因為信號的掛起和阻塞是作為位掩碼(bitmask)實現的,每個信號類型只有一個位。例如,我們可以讓 SIGALRM 和 SIGTERM 同時掛起,但我們不能有兩個 SIGALRM 信號掛起。進程將只收到一個SIGALRM信號,即使是多次拋出。

通過實時信號,信號可以和數據一起排隊,這樣每個信號的實例都可以單獨傳遞和處理。

POSIX沒有規定標準信號的傳遞順序,也沒有規定如果標準信號和實時信號都在等待中會如何處理。然而在Linux中,會優先處理標準信號。對於實時信號,編號較低的信號首先被傳遞,如果一個信號類型有很多在排隊,最早的一個會被首先傳遞。

大事記

  • 1990 信號在 POSIX.1-1990 標準中得到了描述。可以追溯至 IEEE標準1003.1-1988。
  • 1993 實時擴展作為 POSIX.1b 發佈。其中包含實時信號。
  • 1999 隨著內核版本 2.2 的發佈,Linux 開始支持實時信號。
  • 2001 POSIX.1-2001 標準中增加了更多信號:SIGBUS、SIGPOLL、SIGPROF、SIGSYS、SIGTRAP、SIGURG、SIGVTALRM、SIGXCPU、SIGXFSZ。

示例代碼

// Example shows a custom handler for SIGINT
// but the handler reverts to default action for future signals.
// Thus, first ctrl+c will allow program to continue
// and second ctrl+c will terminate the program.

#include <unistd.h>
#include <stdio.h>
#include <signal.h>

void sig_handler1(int num)
{
	printf("You are here becoz of signal: %d\n", num);
	signal(SIGINT, SIG_DFL);
}

int main()
{
	signal(SIGINT, sig_handler1);
	while(1)
	{
		printf("Hello\n");
		sleep(2);
	}
}

參考

  1. 原文鏈接:linux-signals

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

-Advertisement-
Play Games
更多相關文章
  • 微信開放平臺:微信掃碼登錄功能 官方文檔:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html 1. 授權流程說明 微信OAuth2.0授權登錄讓微信用戶使用微信身份安全登錄 ...
  • 《零基礎學Java》 資料庫操作 資料庫基礎 資料庫是一種存儲結構,允許使用各種格式 輸入、處理、檢索 數據,且不用在每次需要數據時重新輸入數據。 select 語句: select語句用於查詢數據表中的數據。 select 語句 語法: select 所選欄位列表 from 數據表名 where ...
  • 在Python的應用實踐過程中,經常會遇到字元串使用的問題,我花了點時間,專門整理了 Python 關於 string 的知識,主要內容 包括以下幾個方面: 為了方便以後查看,速查表的形式整理了 Python字元串的內容,《Python字元串速查表》(V1.0版)一共 5 頁,先來一 張圖看下概覽哈 ...
  • SunnyUI.Net, 基於 C# .Net WinForm 開源控制項庫、工具類庫、擴展類庫、多頁面開發框架 Blog: https://www.cnblogs.com/yhuse Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://git ...
  • 之前寫過一篇如使用阿裡雲上部署.NET 3.1自定義運行時的文章,吐槽一下,雖然現在已經2022年了,但是阿裡雲函數計算的支持依然停留在.NET Core 2.1,更新緩慢,由於程式解包大小的限制,也不能放太複雜的東西的上去,雖然現在.NET 6裁剪包能挺好地解決這個問題,但是心裡還是不爽。 需求 ...
  • 之前曾在《C# 中容易忽視的 Encoding.GetByteCount 記憶體問題》中提到過,可以使用 Encoding.Default.GetByteCount 方法來判斷字元是全寬(寬度為 2)還是半寬(寬度為 1)。 這個方法實際上是計算對字元編碼後產生的位元組數,只是在中文環境下,寬字元在使用 ...
  • 本筆記有特殊目錄,點擊開啟: 專有目錄 在Linux系統中編輯文本總是離不開一位老幫手——Vi。而因為其誕生的年代有些久遠,有些操作在現在看來可能有點“反直覺”。 於是我決定寫這樣一篇小筆記,記錄一下我記憶Vi的這些這些 常用 操作和指令的方法(主要靠的是英語和圖示了)。 當然,正如“好記性不如爛筆 ...
  • Vmware Station安裝Arch Linux 一、測試環境及工具 當前教程在win10環境中進行,網路為有線連接 vmware station版本為 16.2.1 arch linux鏡像為 archlinux-2022.04.05-x86_64.iso 終端工具Xshell 6,也可使用p ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...