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 :
以上, , 如有疏漏, 欢迎指正