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