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函數(shù)
使用signal函數(shù),我們可以捕獲一個信號
-
函數(shù)原型
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
-
參數(shù)說明
signum:信號量,即信號的名字
返回值
returns the previous value of the signal handler, or SIG_ERR on error.handler
如果handler是一個函數(shù)地址,當收到signum信號時,則調用handler函數(shù),該函數(shù)被稱為信號處理函數(shù);
如果handler的值是常量SIG_IGN,表示忽略此信號;后面會有一個示例
如果handler的值是常量SIG_DFL表示按照系統(tǒ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 產生信號的條件
1.4 處理信號的方式
處理信號的方式一共有3種,分別是:捕捉信號 、忽略此信號 和 執(zhí)行系統(tǒng)默認動作
1. 捕捉信號
使用signal函數(shù)可以捕獲信號
- 示例代碼
當捕獲當SIGINT信號時,就調用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;
}
- 輸出結果
2. 忽略此信號
將signal函數(shù)的handler參數(shù)賦值為SIG_IGN,就可以實現(xiàn)忽略此信號的功能
- 示例代碼
當用戶輸出ctrl+c時,產生的SIGINT信號會被忽略
#include "apue.h"
int main(int argc, char const *argv[])
{
signal(SIGINT, SIG_IGN);
for (; ;)
sleep(1);
return 0;
}
- 輸出結果
3. 執(zhí)行系統(tǒng)默認動作
如果沒對信號進行捕獲或者忽略,那么在收到信號時,進行將執(zhí)行系統(tǒng)默認動作。使用man kill可以查看每個信號對應的系統(tǒng)執(zhí)行默認動作。例如,SIGINT的默認Action為exit,即如果進程收到該信號,默認執(zhí)行進程退出。
除了exit,系統(tǒng)的支持的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的命令規(guī)則
root@ubuntu:/home/ckt/work/unix/code/chapter10# echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern
運行上面例子中的signal程序,讓它在后臺運行,使用kill命令發(fā)送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,再收到該信號后,進程會執(zhí)行退出
- 示例代碼
#include "apue.h"
int main(int argc, char const *argv[])
{
for (; ;)
sleep(1);
return 0;
}
- 輸出結果
待續(xù)
... ...