0. 思维导图
1. 信号概念
1.1 信号的名字
每个信号都有一个名字,这些名字以SIG开头。Linux将这些信号定义在/usr/include/bits/signum.h中。
/* Signals. */
#define SIGIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGABRT 6 /* Abort (ANSI). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGBUS 7 /* BUS error (4.2 BSD). */
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
... ...
... ...
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31
1.2 signal函数
使用signal函数,我们可以捕获一个信号
-
函数原型
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
-
参数说明
signum:信号量,即信号的名字
返回值
returns the previous value of the signal handler, or SIG_ERR on error.handler
如果handler是一个函数地址,当收到signum信号时,则调用handler函数,该函数被称为信号处理函数;
如果handler的值是常量SIG_IGN,表示忽略此信号;后面会有一个示例
如果handler的值是常量SIG_DFL表示按照系统默认动作执行。
SIG_IGN、SIG_DFL也定义在/usr/include/bits/signum.h中。
/* Fake signal functions. */
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
1.3 产生信号的条件
1.4 处理信号的方式
处理信号的方式一共有3种,分别是:捕捉信号 、忽略此信号 和 执行系统默认动作
1. 捕捉信号
使用signal函数可以捕获信号
- 示例代码
当捕获当SIGINT信号时,就调用sig_int函数,打印received SIGINT
#include "apue.h"
void sig_int()
{
printf("received SIGINT\n");
return;
}
int main(int argc, char const *argv[])
{
signal(SIGINT, sig_int);
for (; ;)
sleep(1);
return 0;
}
- 输出结果
2. 忽略此信号
将signal函数的handler参数赋值为SIG_IGN,就可以实现忽略此信号的功能
- 示例代码
当用户输出ctrl+c时,产生的SIGINT信号会被忽略
#include "apue.h"
int main(int argc, char const *argv[])
{
signal(SIGINT, SIG_IGN);
for (; ;)
sleep(1);
return 0;
}
- 输出结果
3. 执行系统默认动作
如果没对信号进行捕获或者忽略,那么在收到信号时,进行将执行系统默认动作。使用man kill可以查看每个信号对应的系统执行默认动作。例如,SIGINT的默认Action为exit,即如果进程收到该信号,默认执行进程退出。
除了exit,系统的支持的action还有ignore(忽略)、stop(停止)和core。其中core指的是进程收到信号后会产生一个Core Dump File。
Core Dump File是否生成由Core文件大小决定,Linux中默认的Core文件大小设置为零,也就是不生成Core Dump File。想要生成Core Dump File,需要通过命令 ulimit -c unlimited 来设置Core文件大小为无限制。
root@ubuntu:/home/ckt/work/unix/code/chapter10# ulimit -c unlimited
通过命令**echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern **可以设置Core Dump File的命令规则
root@ubuntu:/home/ckt/work/unix/code/chapter10# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
运行上面例子中的signal程序,让它在后台运行,使用kill命令发送SIGSEGV信号给该进程,由于SIGSEGV的默认action为core,该进程在收到SIGSEGV信号后会生成一个Core Dump File
root@ubuntu:/home/ckt/work/unix/code/chapter10# ./signal &
[1] 16613
root@ubuntu:/home/ckt/work/unix/code/chapter10# jobs
[1]+ Running ./signal &
root@ubuntu:/home/ckt/work/unix/code/chapter10# kill -11 %1
root@ubuntu:/home/ckt/work/unix/code/chapter10#
[1]+ Segmentation fault (core dumped) ./signal
root@ubuntu:/home/ckt/work/unix/code/chapter10# ls -l | grep core
-rw------- 1 root root 253952 Apr 18 01:53 core-signal-16613-1492505601
下面以一段代码演示由于进程没有捕获SIGINT,再收到该信号后,进程会执行退出
- 示例代码
#include "apue.h"
int main(int argc, char const *argv[])
{
for (; ;)
sleep(1);
return 0;
}
- 输出结果
待续
... ...