最近幫着同事搞了一下嵌入式的gtk界面, 中間有用到系統signal來進行進程通訊, 做個簡單的記錄
在使用linux系統信號之前需要先了解一下信號基礎知識, 這里給出一個參考博文, 講的很仔細 : https://www.cnblogs.com/taobataoma/archive/2007/08/30/875743.html
下面是我摘錄的一些個人認為的關鍵點 :
軟中斷信號(signal,又簡稱為信號)用來通知進程發生了異步事件。進程之間可以互相通過系統調用kill發送軟中斷信號
內核也可以因為內部事件而給進程發送信號,通知進程發生了某個事件
注意,信號只是用來通知某進程發生了什么事件,並不給該進程傳遞任何數據
收 到信號的進程對各種信號有不同的處理方法, 處理方法可以分為三類:
第一種是類似中斷的處理程序,對於需要處理的信號,進程可以指定處理函數,由該函數來處 理
第二種方法是,忽略某個信號,對該信號不做任何處理,就象未發生過一樣
第三種方法是,對該信號的處理保留系統的默認值,這種缺省操作,對大部分的信 號的缺省操作是使得進程終止
了解了信號基礎之后, 我們來看一下如何發送信號
通常情況下, 使用 kill 命令可以向指定進程發送指定信號, 對於不同的環境發送的信號是不同的, 使用 kill -l 可以查看能夠發送信號
其中有 SIGUSR1 和 SIGUSR2 兩個信號提供給用戶, 作為自定義信號, 那么如果想進行進程間通訊, 只需要在一個進程里調用 kill 命令, 將指定的信號發送給另一個進程, 並在另一個進程中注冊對應信號的回調函數即可
下面上代碼, 分享我的實現方式
首先是發送信號的進程
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <signal.h> 4 #include <string.h> 5 6 #include <iostream> 7 #include <string> 8 9 //執行命令並返回結果 10 void get_cmd_result(const std::string &_cmd, std::string &_result) 11 { 12 FILE *_cmd_result = popen(_cmd.c_str(), "r"); 13 14 char *buf = new char[256]; 15 memset(buf, 0, sizeof(buf)); 16 17 fread(buf, 1, sizeof(buf), _cmd_result); 18 _result = buf; 19 20 pclose(_cmd_result); 21 delete buf; 22 buf = nullptr; 23 } 24 25 //向給定進程發送SIGUSR1信號 26 void send_proc_SIGUSR1(const std::string &proc_name) 27 { 28 std::string _cmd = "ps -a | grep " + proc_name + " | grep -v grep | awk '{print $1}'"; 29 std::string proc_pid; 30 31 get_cmd_result(_cmd, proc_pid); 32 std::cout << "proc_pid = " << proc_pid << std::endl; 33 34 //system會調用 /bin/sh ,sh環境的信號與bash環境的信號語法不同 35 std::string emit_SIGUSR1_to_proc = "kill -USR1 " + proc_pid; 36 std::cout << "execute cmd : " << emit_SIGUSR1_to_proc << std::endl; 37 38 system(emit_SIGUSR1_to_proc.c_str()); 39 } 40 41 int main() 42 { 43 while (true) 44 { 45 send_proc_SIGUSR1("sig_wait"); 46 sleep(2); 47 } 48 49 return 0; 50 }
下面是接收信號的進程
1 #include <signal.h> 2 #include <unistd.h> 3 4 #include <iostream> 5 6 void signal_handler() 7 { 8 std::cout << "get signal : SIGUSR1" << std::endl; 9 } 10 11 int main() 12 { 13 signal(SIGUSR1, (sighandler_t)signal_handler); 14 15 while(true) 16 { 17 std::cout << "waiting signal..." << std::endl; 18 sleep(3); 19 } 20 21 return 0; 22 }
這里需要注意的點就是, sh和bash環境下, kill 命令發送信號的格式不太一樣, 具體大家可以用/bin/sh 試一下 kill -l
最后將兩段代碼分別編譯生成兩個程序 sig_send 和 sig_wait 並執行, 結果如下
sig_send :
sig_wait :
以上, , 如有疏漏, 歡迎指正