從零開始UNIX環(huán)境高級編程(10):信號

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;
}
  • 輸出結果
signal

3. 執(zhí)行系統(tǒng)默認動作

如果沒對信號進行捕獲或者忽略,那么在收到信號時,進行將執(zhí)行系統(tǒng)默認動作。使用man kill可以查看每個信號對應的系統(tǒng)執(zhí)行默認動作。例如,SIGINT的默認Action為exit,即如果進程收到該信號,默認執(zhí)行進程退出。

man kill

除了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;
}
  • 輸出結果
沒有捕獲**SIGINT**,執(zhí)行系統(tǒng)默認動作

待續(xù)

... ...


參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容