信号通讯是在软件层面上对中断机制的一种模拟。信号是进程间通讯机制中惟一的异步通讯机制。异步
信号能够直接进行用户空间进程和内核进程之间的交互,内核进程也能够利用它来通知用户空间进程发生了哪些系统事件。它能够在任什么时候候发给某一进程,而无需知道该进程的状态。若是该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它为止。函数
信号事件的产生有硬件来源(如按下键盘或者其余硬件故障)和软件来源,软件来源除了软件调用,还包括一些非法运算等操做。指针
进程能够经过3种方式来响应一个信号:rest
一、忽略信号:即对信号不作任何处理,其中,有两个信号不能忽略,SIGKILL & SIGSTOP。code
二、捕捉信号:定义信号处理函数,当信号发生时,执行相应的操做。进程
三、执行默认操做:Linux对每种信号都规定了默认操做,下表包含了部分的定义:事件
信号的相关函数包括信号的发送和设置,具体以下:字符串
发送信号的函数:kill() raise() sigqueue()get
设置信号的函数:signal() sigaction() setitimer()原型
其余函数:alarm() pause()
信号发送:kill() raise()
kill() 函数同kill 系统命令同样,能够发送信号给进程或是进程组(实际上,kill 系统命令就是调用 kill() 函数。须要注意的是,它不只能够终止进程(发送 SIGTERM信号),也能够向进程发送其余信号。
注意:raise() 函数只能向进程自身发送信号
函数原型:
int kill(pid_t pid,int sig);
int raise(int sig);
说明:pid 为进程号;sig 为信号类型号
raise() 例程:进程在执行while(1)循环输出字符串的时候调用raise(SIGSTOP)使进程中止 \
/* raise.c */ #include <signal.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { printf("PID: %d\n",getpid()); while(1){ printf("run\n"); raise(SIGSTOP); } }
程序输出:
PID: 55859 run [1]+ Stopped ./a.out
能够看到,进程在输出了第句run以后调用raise(SIGSTOP)使进程中止了,使用命令 "ps -ef | grep a.out" 能够看到进程并无消失,确认进程只是暂停。使用 "kill -9 55859" 杀死进程。
kill() 例程:子进程间隔10us打印一串字符,父进程100us后 kill 子进程。
/* kill.c */ #include <signal.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> int main() { pid_t pid; pid = fork(); if(pid == -1){ perror("fork failed:"); exit(-1); } if(pid == 0){ while(1){ printf("child\n"); sleep(1); } }else{ sleep(3); kill(pid,SIGINT); sleep(3); exit(0); } }
alarm() 能够在进程中设置一个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号。一个进程只能有一个闹钟,重复设置,前面的闹钟会被覆盖。
示例:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { alarm(3); while(1){ printf("run\n"); sleep(1); pause(); } printf("waken up\n"); }
程序输出:
run Alarm clock
注释掉 pause(); 的程序输出:
run run run Alarm clock
信号的设置:signal() sigaction()
signal() 用于设置信号的处理函数。主要用于前32种非实时信号的处理,不支持信号传递信息。
注:signal() 是UNIX系统的遗留版本,不一样的系统表现不一且在有的系统上会出现信号丢失的问题。且在man中亦提到,’应避免使用signal(),使用sigaction()代替‘。因此这里咱们就不讨论signal(),直接使用sigaction()。
函数原型:
int sigaction(int signum,const struct sigaction *act,struct sigacton *oldact);
说明:signum - 信号类型,除SIGKILL & SIGSTOP 外的任何一个信号;act - 指向sigaction结构体的指针,包含对特殊信号的处理;oldact - 保留信号原先的处理方式。
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
说明:
sa_handler 和 sa_sigaction 二者只能定义一个,且sa_sigaction 是 sa_handler的升级版本,因为sa_sigaction又太复杂,在这里咱们就不讨论sa_sigaction。
sa_handler 是一个函数指针,指向信号处理函数。它既能够是用户自定义的处理函数,也能够为SIG_DFL(采用默认的处理方式)或SIG_IGN(忽略信号)。信号处理函数只有一个参数,即信号类型。
sa_mask是一个信号集合,用来指定在信号处理函数执行过程当中哪些信号被屏蔽。
sa_flags 中包含了许多标志位,都是和信号处理相关的选项。常见可选值包括(SA_NODEFER/SA_NOMASK/SA_NOCLDSTOP/SA_RESTART/SA_ONESHOT/SA_RESETHAND)
sigaction() 示例:
/* signal.c */ #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void my_func(int sign_no) { if(sign_no == SIGINT){ printf("I have got SIGINT\n"); }else if(sign_no == SIGQUIT){ printf("I have got SIGQUIT\n"); } } int main() { struct sigaction action; //初始化结构体 sigaction(SIGINT,0,&action); action.sa_handler = my_func; sigaction(SIGINT,&action,0); sigaction(SIGQUIT,0,&action); action.sa_handler = my_func; sigaction(SIGQUIT,&action,0); printf("Waiting for signal SIGINT & SIGQUIT\n:"); pause(); exit(0); }