信号是unix和Linux系统相应某些条件而产生的一个事件。接收到信号的进程会相应的采取一些行动。
信号 值 处理动作 发出信号的原因
----------------------------------------------------------------------
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写
程序可以用signal库函数来处理信号,它的定义如下所示。
#include<signal.h>
void (*signal (int sig , void (*func)(int ) ) )(int );
这是一个相当复杂的函数声明,signal是一个带有sig和func两个参数的函数。准备捕获或忽略的信号由参数sig给出,接收到
指定的信号后将要调用的函数有参数func给出。信号处理函数必须有一个int类型的参数(即接收到的信号代码)并且返回类型为
void。
SIG_IGN 忽略信号
SIG_DFL 恢复默认行为
/* We'll start by writing the function which reacts to the signal
which is passed in the parameter sig.
This is the function we will arrange to be called when a signal occurs.
We print a message, then reset the signal handling for SIGINT
(by default generated by pressing CTRL-C) back to the default behavior.
Let's call this function ouch. */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch(int sig)
{
printf("OUCH! - I got signal %d\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
/* The main function has to intercept the SIGINT signal generated when we type Ctrl-C .
For the rest of the time, it just sits in an infinite loop,
printing a message once a second. */
int main()
{
(void) signal(SIGINT, ouch);
while(1) {
printf("Hello World!\n");
sleep(1);
}
}
发送信号
#include<sys/types.h>
#include<signal.h>
int kill(pid_t pid, int sig);
kill函数把参数sig给定的信号发送给由参数pid给出的进程号所指定的的进程。成功是返回0。
kill调用会在失败时返回-1并设置errno变量。
信号向我们提供了一个有用的闹钟功能。进程可以调用alarm函数在经过预定时间后发送一个SIGALRM信号、
#include<unistd.h>
unsigned int alarm(unsigned int seconds);
alarm函数用来在seconds秒之后安排发送一个SIGALRM信号。
/* In alarm.c, the first function, ding, simulates an alarm clock. */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
static int alarm_fired = 0;
void ding(int sig)
{
alarm_fired = 1;
}
/* In main, we tell the child process to wait for five seconds
before sending a SIGALRM signal to its parent. */
int main()
{
pid_t pid;
printf("alarm application starting\n");
pid = fork();
switch(pid) {
case -1:
/* Failure */
perror("fork failed");
exit(1);
case 0:
/* child */
sleep(5);
kill(getppid(), SIGALRM);
exit(0);
}
/* The parent process arranges to catch SIGALRM with a call to signal
and then waits for the inevitable. */
printf("waiting for alarm to go off\n");
(void) signal(SIGALRM, ding);
pause();
if (alarm_fired)
printf("Ding!\n");
printf("done\n");
exit(0);
}