信号(Signals)是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。
信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。也可以简单理解为信号是某种形式上的软中断。
一般情况下,信号的来源可分为以下三种:
kill
命令向进程发送任务信号、进程调用kill
或sigqueue
函数发送信号、当检测到某种软件条件已经具备时发出信号,如由alarm
或settimer
设置的定时器超时时将生成SIGALRM
信号等多种情景均可产生信号。Ctrl+C
将产生一个SIGINT
信号,Ctrl+\
产生一个SIGQUIT
信号等。可运行kill -l
查看Linux支持的信号列表:
sl@Li:~/Works$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
可以看到Linux中系统一共支持64种信号,其中1到31号信号为普通信号(也程为不可靠信号),34到64为实时信号(可靠信号)。
可靠信号与不可靠信号的区别:
以下列出几个常用的信号:
Ctrl+C
)时发出,用于通知前台进程组终止进程。SIGINT
类似, 但由QUIT字符(通常是Ctrl+\
)来控制. 进程在因收到SIGQUIT
退出时会产生core
文件, 在这个意义上类似于一个程序错误信号。SIGKILL
不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出。要注意信号处理函数的可重入问题,因为信号处理函数执行过程中有可能被其他信号再次中断,这时程序会跳到另一个信号的处理函数中,处理完成后再次返回当前处理函数,编写自己定义的信号处理函数的时候一定要注意这一点。信号可以理解为“软中断”,这样可重入函数就很好理解了。
内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。 所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。
内核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态。当进程接收到一个它忽略的信号时,进程丢弃该信号,就像没有收到该信号似的继续运行。
如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,才返回原先进入内核的地方。 这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。
下面引用一个例子说明这个过程:
SIGQUIT
信号的处理函数sighandler
。main
函数,这时发生中断或异常切换到内核态。main
函数之前检查到有信号SIGQUIT
递达。main
函数的上下文继续执行,而是执行sighandler
函数,sighandler
和main
函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程。sighandler
函数返回后自动执行特殊的系统调用sigreturn
再次进入内核态。main
函数的上下文继续执行了。下面的代码收到程序退出信号后会执行用户定义的信号处理函数来替代系统默认的处理程序。
#include<stdlib.h>
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>
void sig_handle(int sig) {
printf("received signal: %d, quit.\n", sig);
exit(0);
}
int main () {
signal(SIGINT, sig_handle);
signal(SIGKILL, sig_handle);
signal(SIGSEGV, sig_handle);
signal(SIGTERM, sig_handle);
int i = 0;
while (1) {
printf("%d\n", ++i);
sleep(2);
}
printf("main quit.");
return 0;
}
运行结果:
1
2
received signal: 15, quit.
这段代码功能与上面的例子差不多,信号也可以传参,但是更多的是通知功能,可传递的信息非常有限,如果需要传递大量的信息,可以考虑其他进程间通信方式。
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
void new_op(int, siginfo_t*, void*);
int main() {
if (NULL == freopen("sigproc.log", "w", stdout)) {
fprintf(stderr, "error redirecting stdout\n");
}
struct sigaction act;
sigemptyset(&act.sa_mask); //sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送
sigaddset(&act.sa_mask, SIGTERM);
sigaddset(&act.sa_mask, SIGINT);
act.sa_flags = SA_SIGINFO; //SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中
act.sa_sigaction = new_op;
if (sigaction(SIGINT, &act, NULL) < 0) {
printf("install sigal error\n");
}
if (sigaction(SIGTERM, &act, NULL) < 0) {
printf("install sigal error\n");
}
if (sigaction(SIGHUP, &act, NULL) < 0) {
printf("install sigal error\n");
}
int i = 0;
while (1) {
printf("%d\n", ++i);
sleep(1);
}
printf("end.");
return 0;
}
void new_op(int signum, siginfo_t *info, void *myact) {
printf("receive signal %d\n", signum);
for (int i = 0; i < 5; ++i) {
printf("signal processing: %d\n", i);
sleep(1);
}
printf("process quit.");
exit(0);
}
运行结果:
1
2
3
receive signal 15
signal processing: 0
signal processing: 1
signal processing: 2
signal processing: 3
signal processing: 4
process quit.
原文:https://www.cnblogs.com/s-lisheng/p/11264367.html