Ctrl-C中断当前运行的程序。这个中断由一个称为信号的内核机制产生。
什么是信号,它从哪里来
- 用户
用户能够通过Ctrl-C、Ctrl-Z或是终端驱动程序分配给信号控制字符的其他按键来请求内核产生信号。 - 内核
当进程执行出错时,内核给进程发送一个信号,如非法读取内存,浮点数溢出。 - 进程
一个进程可以通过系统调用kill
给另一个进程发送信号。即,进程间可以通过信号机制进行通信。
由于进程的某个操作所产生的信号叫同步信号
,如除数为0;由于用户键盘输入的进程外信号叫异步信号
。
信号代码定义在/usr/include/signal.h
中。
进程如何处理信号
当进程收到SIGINT
时,并不一定销毁。进程通过系统调用signal
告诉内核自己想怎样处理这个信号。具体有三种选择
- 默认处理(通常是消亡)
每个信号都有自己的默认处理方式。SIGINT
的默认处理方式是消亡。进程可以通过下列调用恢复默认处理signal(SIGINT, SIG_DEL);
- 忽略信号
signal(SIGINT, SIG_IGN);
- 调用函数
告诉内核收到信号时,调用自定义的函数signal(SIGINT, func);
func
进行处理。这适用于发生中断时进行必要的清理工作。
简单的例子
#include <signal.h>
#include <stdio.h>
int main()
{
void f(int); // 信号处理函数
int i;
signal(SIGINT, f); //注册处理函数
for(i=0; i<5; ++i)
{
printf("hello signal!\n");
sleep(1);
}
return 1;
}
void f(int signum)
{
printf("dolly\n");
}
程序由两部分组成:main函数和信号处理函数f。程序首先照常执行main函数的循环,如果进程收到SIGINT
信号,内核函数会调用注册的f函数,然后返回到跳转前的位置。
考虑一个问题:屏蔽所有信号并在程序中执行死循环,程序会一直执行下去,无法干涉吗?
实际上Unix不允许这种情况发生,因为并不是所有的信号都允许被忽略:SIGKILL
和SIGSTOP
。