Unix 訊號

在計算機科學中，訊號（Signals）是 Unix、類 Unix 以及其他 POSIX 相容的作業系統中程序間通訊的一種有限制的方式。它是一種非同步的通知機制，用來提醒程序一個事件已經發生。當一個訊號傳送給一個程序，作業系統中斷了程序正常的控制流程，此時，任何非原子操作都將被中斷。如果程序定義了訊號的處理函式，那麼它將被執行，否則就執行預設的處理函式。

訊號類似於中斷，不同之處在於中斷由處理器調解並由核心處理，而訊號由核心調解 (可能透過系統呼叫) 並由程序處理。核心可以將中斷作為訊號傳遞給導致中斷的程序（典型的例子有 SIGSEGV、SIGBUS、SIGILL 和 SIGFPE）。

訊號起源於 20 世紀 70 年代的貝爾實驗室 Unix，最近在 POSIX 標準中有所規定。

嵌入式程式可能會發現訊號對於程序間通訊很有用，因為訊號的計算和記憶體佔用很小。

傳送訊號

在一個執行的程式的控制終端鍵入特定的組合鍵可以向它傳送某些訊號：
Ctrl-C 傳送 INT 訊號（SIGINT）；預設情況下，這會導致程序終止。
Ctrl-Z 傳送 TSTP 訊號（SIGTSTP）；預設情況下，這會導致程序掛起。
Ctrl-\ 傳送 QUIT 訊號（SIGQUIT）；預設情況下，這會導致程序終止並且將記憶體中的資訊轉儲到硬碟（核心轉儲）。
（這些組合鍵可以透過 stty 命令來修改。）
kill 系統呼叫會在許可權允許的情況下向程序傳送特定的訊號，類似地，kill 命令允許使用者向程序傳送訊號。raise (3) 庫函式可以將特定訊號傳送給當前程序。
像除數為零、段錯誤這些異常也會產生訊號（這裡分別是 SIGFPE 和 SIGSEGV，預設都會導致程序終止和核心轉儲）。
核心可以向程序傳送訊號以告知它一個事件發生了。例如當程序將資料寫入一個已經被關閉的管道時將會收到 SIGPIPE 訊號，預設情況下會使程序關閉。

處理訊號

訊號處理函式可以透過 signal 系統呼叫來設定。如果沒有為一個訊號設定對應的處理函式，就會使用預設的處理函式，否則訊號就被程序截獲並呼叫相應的處理函式。在沒有處理函式的情況下，程式可以指定兩種行為：忽略這個訊號（SIGIGN）或者用預設的處理函式（SIGDFL）。但是有兩個訊號是無法被截獲並處理的：SIGKILL 和 SIGSTOP。

2.1 風險

因為競態條件的存在，訊號的處理是有弱點的。因為訊號是非同步的，所以在處理一個訊號的過程中，程序可能收到另一個訊號（甚至是相同的訊號）。sigprocmask 系統呼叫可以用來阻塞和恢復訊號的傳遞。訊號可以造成程序中系統呼叫的中斷，並在訊號處理完後重新開始未完成的系統呼叫。訊號處理函式應該沒有任何不想要的副作用，比如，errno 的改變、訊號掩碼的改變、訊號處理方法的改變，以及其他全域性程序性質的改變。在訊號處理函式內使用不可重入函式，如 malloc 和 printf，也是不安全的。

與硬體異常的關係

程序的執行也可能導致硬體異常，例如，將一個數除以零，或者出現 TLB 不命中。在類 Unix 系統中，這會自動執行核心的異常處理程式。對於某些異常如頁缺失，核心有足夠的資訊來處理完並恢復程序的執行。但是對於另外一些異常，核心不能處理而只能透過傳送訊號把異常交給程序自己處理。例如在 x86 架構的 CPU 上，如果一個程序嘗試將一個數除以零，將會產生 divide error 異常，並使核心向出錯的程序傳送 SIGFPE 訊號。相似地，如果一個程序嘗試訪問虛擬地址空間以外的記憶體，核心將向程序傳送 SIGSEGV 訊號。異常與訊號的具體對應關係在不同的 CPU 架構上是不同的。

訊號列表

單一 UNIX 規範規定了在中定義的訊號有：

備註：打星號的部分表示這是 X/Open System Interfaces (XSI) 擴充的部分。使用引號的文字是引用自 SUS 。

 }} 和}}

SIGABRT 和 SIGIOT 訊號能讓程式異常終止（abort）。 該訊號通常是由程序自身呼叫 C 標準函式庫 的 abort 函式來觸發， 但它也可以像其它訊號一樣由外部發送給程序。}}, }} 和}}

如果你用 setitimer 這一類的報警設定函式設定了一個時限，到達時限時程序會接收到 SIGALRM, SIGVTALRM 或者 SIGPROF。但是這三個訊號量的含義各有不同，SIGALRM 計時的是真即時間，SIGVTALRM 計時的是程序使用了多少 CPU 時間，而 SIGPROF 計時的是程序和代表該程序的核心用了多少時間。

 }}

匯流排發生錯誤時，程序接收到一個 SIGBUS 訊號。舉例來說，儲存器訪問對齊或者或不存在對應的物理地址都會產生 SIGBUS 訊號。

 }}

當子程序終止、被中斷或被中斷後恢復時，SIGCHLD 訊號被髮送到程序。該訊號的一個常見用法是指示作業系統在子程序終止後清理其使用的資源，而不顯式呼叫等待系統呼叫。

 }}

SIGCONT 訊號指示作業系統繼續 (重啟) 先前由 SIGSTOP 或 SIGTSTP 訊號暫停的程序。Unix 殼的作業控制是該訊號的一個重要應用。

 }}

當程序執行了一個錯誤的算術運算時，例如被零除，訊號被髮送到一個程序。這可能包括整數被零除，以及整數在除結果中溢位（在 C 中只有 INTMIN/-1、INT64MIN/-1 和 %-1 會觸發該行為）。注意該訊號與浮點數溢位無關。

 }}

檢測到控制中斷掛起或者控制程序死亡時，程序會收到 SIGHUP。現在作業系統，該訊號通常意味著使用的 虛擬終端 已經被關閉。許多 守護程序 在接收到該訊號時，會過載他們的設定和重新開啟日誌檔案（logfiles），而不是去退出程式。nohup 命令用於無視該訊號。

 }}

當程序試圖執行非法、格式錯誤、未知或特權指令時，SIGILL 訊號被髮送到該程序。

 }}

當用戶希望中斷程序時，SIGINT 訊號由使用者的控制終端傳送到程序。這通常透過按下 Ctrl+C 來發送，但是在某些系統中，可以使用 “DELETE” 鍵或 “BREAK” 鍵。

 }}

傳送 SIGKILL 訊號到一個程序可以使其立即終止（KILL）。與 SIGTERM 和 SIGINT 相不同的是，這個訊號不能被捕獲或忽略，接收過程在接收到這個訊號時不能執行任何清理。以下例外情況適用：

殭屍程序不能被殺死，因為它們已經死了，正在等待它們的父程序來收穫它們。
處於阻塞狀態的程序不會死亡，直到它們再次醒來。
init 程序是特殊的： init 不接收任何它不打算處理的訊號，因此它會忽略 SIGKILL。這條規則有一個例外，Linux 上的 init 如果被 ptrace 了，那麼它是可以接收 SIGKILL 並被殺死的。
處於不可中斷的睡眠的程序即使傳送了 SIGKILL，也有可能不會終止（並釋放其資源）。這是少數 Unix 系統必須重新啟動才能解決臨時軟體問題的幾種情況之一。

當在大多數系統關閉程式中終止程序時，如果程序沒有響應 SIGTERM 而自動退出，SIGKILL 是最後的手段。為了加快電腦關機過程，Mac OS X 10.6 向標記自己為 “clean” 的程序傳送 SIGKILL，從而加快關機時間，而且可能不會產生任何不良影響。。在 Linux 中執行 killall -9 命令具有類似不過更危險的效果；它不讓程式儲存未儲存的資料。

 }}

當一個程序試圖寫入一個沒有連線到另一端程序的管道時，SIGPIPE 訊號會被髮送到該程序。

 }}

當一個事件發生在一個正在顯式監視的檔案描述符上時，就會發送 SIGPOLL 訊號。有效使用這種用法可以進行非同步 I/O，因為核心將代替呼叫者輪詢描述符。它提供了主動輪詢的替代方案。

 }} 到}}

SIGRTMIN 至 SIGRTMAX 訊號用於使用者自定義的目的。它們是即時訊號。

 }} 和}}

當程序在後臺試圖分別從 tty 讀取或寫入時，SIGTTIN 和 SIGTTOU 訊號會被髮送到該程序。通常，這些訊號僅由作業控制下的程序接收；守護程序沒有控制終端，因此永遠不會接收這些訊號。

 }}

當用戶在程序的控制終端請求退出程序並進行核心轉儲時，SIGQUIT 訊號會被髮送到該程序。

 }}

當程序試圖訪問無效記憶體引用時發生儲存器區段錯誤，SIGSEGV 訊號會被髮送到該程序。

 }}

當作業系統暫停程序的執行時，會產生 SIGSTOP 訊號。SIGSTOP 訊號無法被捕獲或無視。

 }}

當系統呼叫時傳入非法的引數，會產生 SIGSYS 訊號。實際上，SIGSYS 訊號很少會出現，因為應用程式依賴庫呼叫系統呼叫。SIGSYS 可以被違反 Linux Seccomp 安全規則的應用程式捕獲。SIGSYS 也可用於模擬外部系統呼叫，例如：在 Linux 上模擬 Windows 系統呼叫。

 }}

當用戶請求終止程序時，會產生 SIGTERM 訊號。SIGTERM 訊號可以被捕獲或無視。這允許該程序在結束前釋放掉所佔用的資源並儲存其狀態。SIGINT 和 SIGTERM 非常相似。

 }}

當用戶在程序的控制終端請求退出程序時，會產生 SIGTSTP 訊號。SIGTSTP 訊號可以被捕獲或無視。SIGTSTP 訊號的產生通常是由於使用者按下。

4.1 預設行為

一個程序可以自定義如何處理傳入的 POSIX 訊號。如果一個程序沒有定義一個訊號處理程式，那麼這個訊號的預設處理程式將被使用。下表列出了一些與 POSIX 相容的 UNIX 系統的預設操作，例如 FreeBSD、OpenBSD 和 Linux。

 可移植編號

對於大多數訊號，相應的訊號編號由實現定義。此列列出了 POSIX 標準中指定的數字。

 行為釋義

 終止 程序異常終止。程序終止的結果和呼叫 _exit 是一樣的，除了終止可以向 wait 和 waitpid 返回導致程序終止的訊號。

 終止（核心轉儲） 程序異常終止。這種程序中止的過程根據實現有所不同，一般會建立一個核心檔案。

 忽略 程序忽略該訊號。

 暫停 程序被暫停（不是終止）。

 繼續 程序恢復執行。