嵌入式Linux:發送實時信號
非實時信號有一個明顯的局限性:當同一個信號多次發生時,它只會被記錄為一次,且不會記錄發生的次數。因此,當該信號被解除阻塞后,它僅會被處理一次。這種行為使得標準信號在某些應用場景下不夠靈活。
相比之下,實時信號 提供了幾個關鍵的優勢:
信號范圍擴大:標準信號僅提供 SIGUSR1 和 SIGUSR2 供用戶自定義使用,而實時信號的編號范圍更大(SIGRTMIN 到 SIGRTMAX,對應編號范圍 34~64),可以應用于更多自定義目的。
隊列化管理:實時信號采取隊列化管理,這意味著如果同一個實時信號多次發生,內核將記錄每次事件并按順序傳遞,而標準信號只會傳遞一次。
附帶數據:實時信號允許攜帶附帶數據(可以是整型數據或指針),供接收方在信號處理函數中使用,這為信號傳遞帶來了更大的靈活性。
傳遞順序保證:當多個不同的實時信號處于等待狀態時,信號編號越小的信號會優先傳遞。如果同一個信號多次發生,傳遞順序會與發送順序保持一致。
為了使用實時信號,通常需要滿足以下要求:
發送實時信號:發送進程需要使用 sigqueue() 系統調用發送實時信號及其伴隨數據。
接收實時信號:接收進程需要為該信號設置信號處理函數,并在 sigaction 函數中啟用 SA_SIGINFO 標志,以確保可以接收伴隨數據。
sigqueue() 的函數原型如下:
#include <signal.h>int sigqueue(pid_t pid, int sig, const union sigval value);
參數:
pid:接收信號的進程 ID。
sig:需要發送的信號編號。與 kill() 類似,也可以將 sig 設置為 0 來檢查進程是否存在。
value:一個 union sigval 類型的值,表示伴隨信號傳遞的數據,可以是整型或指針。
返回值:
成功返回 0;
失敗返回 -1,并設置 errno。
union sigval 是一個共用體,定義如下:
typedef union sigval { int sival_int; // 整型數據 void *sival_ptr; // 指針數據} sigval_t;
1
發送進程
使用 sigqueue() 向另一個進程發送實時信號及其伴隨數據。
#include <stdio.h>#include <stdlib.h>#include <signal.h> int main(int argc, char *argv[]) { union sigval sig_val; int pid, sig; // 檢查參數個數 if (argc < 3) { exit(-1); } // 獲取命令行傳遞的參數 pid = atoi(argv[1]); sig = atoi(argv[2]); printf("Sending signal %d to process %d\n", sig, pid); // 發送信號,附帶整型數據 sig_val.sival_int = 10; if (sigqueue(pid, sig, sig_val) == -1) { perror("sigqueue error"); exit(-1); } puts("Signal sent successfully!"); return 0;}
2
接收進程
使用 sigaction() 綁定實時信號處理函數,并接收伴隨數據。
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <unistd.h> static void sig_handler(int sig, siginfo_t *info, void *context) { sigval_t sig_val = info->si_value; printf("Received real-time signal: %d\n", sig); printf("Attached data: %d\n", sig_val.sival_int);} int main(int argc, char *argv[]) { struct sigaction sa = {0}; int sig; // 檢查參數個數 if (argc < 2) { exit(-1); } // 獲取命令行傳遞的信號編號 sig = atoi(argv[1]); // 綁定信號處理函數 sa.sa_sigaction = sig_handler; sa.sa_flags = SA_SIGINFO; // 啟用 SA_SIGINFO 標志,以接收附帶數據 if (sigaction(sig, &sa, NULL) == -1) { perror("sigaction error"); exit(-1); } // 無限循環,等待信號 while (1) { sleep(1); } return 0;}
標準信號和實時信號在 Linux 信號處理機制中各有優劣。標準信號適用于大多數常見場景,但其無法記錄信號的多次發生,且缺少附帶數據傳遞的能力。而實時信號則提供了更靈活的功能,包括多次傳遞信號、附帶數據和保證傳遞順序。這些特性使得實時信號在高性能和復雜信號處理需求下尤為有用。
*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。