Linux C++ 通過信號進行跨進程通訊


最近幫着同事搞了一下嵌入式的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 :

 

 以上, , 如有疏漏, 歡迎指正


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM