进程间通信IPC-信号
1,signal-ANSI C信号处理
1 #include <signal.h> 2 typedef void (*sighandler_t)(int); 3 sighandler_t signal(int signum, sighandler_t handler);
signal是ANSI C实现的信号处理函数,signum表示信号ID,常用的信号有:
1 ~$ kill -l 2 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 3 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 4 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 5 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 6 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 7 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 8 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 9 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 10 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 11 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 13 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 14 63) SIGRTMAX-1 64) SIGRTMAX
每个信号的含义和产生可以通过 查看linux编程手册:man 7 signal
handler参数有3种:
a)SIG_IGN,表示忽略该信号
b)SIG_DFL,表示捕捉到某信号采用系统默认的处理方式,查看signal(7)
c)自定义信号处理函数,如下:
1 #include <signal.h> 2 void my_signal_handler(int sig) 3 { 4 //do something 5 } 6 7 int main(int argc, char* argv[]) 8 { 9 singal(SIGUSR1, my_signal_handler); //注册信号捕捉函数 10 //do something 11 return 0; 12 }
2,sigaction-信号处理system call
1 #include <signal.h> 2 int sigactoin(int signum, const struct sigaction *act, struct sigaction *oldact);//注册信号处理 3 int sigemptyset(sigset_t *set);//清空全部信号sigset_t,用于sa_mask 4 int sigfillset(sigset_t *set);//填充全部信号sigset_t,用于sa_mask 5 int sigaddset(sigset_t *set, int signum);//增加某信号到sigset_t,用于sa_mask 6 int sigdelset(sigset_t *set, int signum);//从sigset_t中删除某信号,用于sa_mask 7 int sigismember(const sigset_t *set, int signum);//是否存在 8 struct sigaction { 9 void (*sa_handler)(int); //默认信号处理函数 10 void (*sa_sigaction)(int, siginfo_t *, void *); //sa_flag设置为SA_SIGINFO时常用的信号处理函数 11 sigset_t sa_mask; //屏蔽信号集合 12 int sa_flags; //定义的行为 13 void (*sa_restorer)(void); //已弃用 14 }; 15 16 17 #include <stdlib.h> 18 #include <signal.h> 19 20 void my_signal_handler(int sig) 21 { 22 //do something 23 } 24 25 int addmysignal(int signum, void (* my_signal_handler)(int)) 26 { 27 struct sigaction sa; 28 memset(&sa, 0, sizeof(sa)); 29 sa.sa_handler = my_signal_handler; 30 sa.sa_flags |= SA_RESTART; //自动重启该信号signum捕捉 31 sigfillset(&sa.sa_mask); //屏蔽(阻塞)所有其他信号,当捕捉到signum并执行信号处理函数时。 32 return sigaction(signum, &sa, NULL);//这里暂时忽略oldact; 33 } 34 35 int main(int argc, char* argv[]) 36 { 37 //注册信号捕捉函数 38 if (addmysignal(SIGUSR1, my_signal_handler) < 0) 39 { 40 exit(EXIT_FAILURE); 41 } 42 //do something 43 return 0; 44 }
sa_flags参数可通过查看linux编程手册进一步了解:man sigaction
从上述两种信号处理的使用方式来看,好像没有进程间通信什么事。那进程间是如何利用signal来进行通信的呢?
1 #include <sys/types.h> 2 #include <signal.h> 3 int kill(pid_t pid, int sig);
通过系统调用kill向指定进程发送指定信号,pid进程收到sig后,执行信号处理函数,这就实现了进程间通信。
同时我们在使用信号进程通信的同时,还可以借助管道,实现两进程间的数据交互。
示例代码略。