0. 思維導(dǎo)圖

1. 信號(hào)概念
1.1 信號(hào)的名字
每個(gè)信號(hào)都有一個(gè)名字,這些名字以SIG開頭。Linux將這些信號(hào)定義在/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函數(shù)
使用signal函數(shù),我們可以捕獲一個(gè)信號(hào)
-
函數(shù)原型
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); -
參數(shù)說明
signum:信號(hào)量,即信號(hào)的名字
返回值
returns the previous value of the signal handler, or SIG_ERR on error.handler
如果handler是一個(gè)函數(shù)地址,當(dāng)收到signum信號(hào)時(shí),則調(diào)用handler函數(shù),該函數(shù)被稱為信號(hào)處理函數(shù);
如果handler的值是常量SIG_IGN,表示忽略此信號(hào);后面會(huì)有一個(gè)示例
如果handler的值是常量SIG_DFL表示按照系統(tǒng)默認(rèn)動(dòng)作執(zhí)行。
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 產(chǎn)生信號(hào)的條件

1.4 處理信號(hào)的方式
處理信號(hào)的方式一共有3種,分別是:捕捉信號(hào) 、忽略此信號(hào) 和 執(zhí)行系統(tǒng)默認(rèn)動(dòng)作
1. 捕捉信號(hào)
使用signal函數(shù)可以捕獲信號(hào)
- 示例代碼
當(dāng)捕獲當(dāng)SIGINT信號(hào)時(shí),就調(diào)用sig_int函數(shù),打印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;
}
- 輸出結(jié)果

2. 忽略此信號(hào)
將signal函數(shù)的handler參數(shù)賦值為SIG_IGN,就可以實(shí)現(xiàn)忽略此信號(hào)的功能
- 示例代碼
當(dāng)用戶輸出ctrl+c時(shí),產(chǎn)生的SIGINT信號(hào)會(huì)被忽略
#include "apue.h"
int main(int argc, char const *argv[])
{
signal(SIGINT, SIG_IGN);
for (; ;)
sleep(1);
return 0;
}
- 輸出結(jié)果

3. 執(zhí)行系統(tǒng)默認(rèn)動(dòng)作
如果沒對(duì)信號(hào)進(jìn)行捕獲或者忽略,那么在收到信號(hào)時(shí),進(jìn)行將執(zhí)行系統(tǒng)默認(rèn)動(dòng)作。使用man kill可以查看每個(gè)信號(hào)對(duì)應(yīng)的系統(tǒng)執(zhí)行默認(rèn)動(dòng)作。例如,SIGINT的默認(rèn)Action為exit,即如果進(jìn)程收到該信號(hào),默認(rèn)執(zhí)行進(jìn)程退出。

除了exit,系統(tǒng)的支持的action還有ignore(忽略)、stop(停止)和core。其中core指的是進(jìn)程收到信號(hào)后會(huì)產(chǎn)生一個(gè)Core Dump File。
Core Dump File是否生成由Core文件大小決定,Linux中默認(rèn)的Core文件大小設(shè)置為零,也就是不生成Core Dump File。想要生成Core Dump File,需要通過命令 ulimit -c unlimited 來設(shè)置Core文件大小為無限制。
root@ubuntu:/home/ckt/work/unix/code/chapter10# ulimit -c unlimited
通過命令**echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern **可以設(shè)置Core Dump File的命令規(guī)則
root@ubuntu:/home/ckt/work/unix/code/chapter10# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
運(yùn)行上面例子中的signal程序,讓它在后臺(tái)運(yùn)行,使用kill命令發(fā)送SIGSEGV信號(hào)給該進(jìn)程,由于SIGSEGV的默認(rèn)action為core,該進(jìn)程在收到SIGSEGV信號(hào)后會(huì)生成一個(gè)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
下面以一段代碼演示由于進(jìn)程沒有捕獲SIGINT,再收到該信號(hào)后,進(jìn)程會(huì)執(zhí)行退出
- 示例代碼
#include "apue.h"
int main(int argc, char const *argv[])
{
for (; ;)
sleep(1);
return 0;
}
- 輸出結(jié)果

待續(xù)
... ...