信號#1

信號的概念

取決于進程的要求,內(nèi)核對Signal信號有如下三種行為:

  1. 忽略信號
  2. 抓住這個信號并且對這個信號進行處理
  3. 采取默認行為

信號標識符Signal Identifiers

Signals#1

Signals#2

在Linux中, SIGINFO = SIGPWR | SIGIOT = SIGABRT | SIGPOLL = SIGLOST = SIGIO

  • SIGABRT
    函數(shù)abort將此信號發(fā)送給調(diào)用它的進程。然后,該進程終止并生成一個core file。在Linux中,在條件不滿足時,斷言assert()調(diào)用abort() 。
  • SIGALRM
    alarm()和setitimer()函數(shù)(帶有ITIMER_REAL標志)將此信號發(fā)送給在警報過期時調(diào)用它們的進程。
  • SIGBUS
    當進程發(fā)生內(nèi)存保護(這個會出發(fā)SIGSEGV)以外的硬件故障時,內(nèi)核會引發(fā)此信號。
  • SIGCHLD
    每當進程終止或停止時,內(nèi)核都會向進程的父進程發(fā)送此信號。由于默認情況下忽略SIGCHLD, 所以進程必須顯式的捕獲并處理他們感興趣的子進程。此信號的處理程序通常調(diào)用wait()。
  • SIGCONT
    當進程在停止后恢復時,內(nèi)核將此信號發(fā)送給進程。默認情況下,此信號將被忽略,但如果進程希望在繼續(xù)之后進行一個特殊的行為則可以抓住他。此信號通常由希望刷新屏幕的終端或編輯器使用。
  • SIGFPE
    此信號表示任何算術(shù)異常,而不僅僅是那些與浮點操作相關(guān)的異常。
  • SIGHUP
    當會話session的終端斷開時,內(nèi)核將此信號發(fā)送給會話領導人seesion leader。
  • SIGILL
    當進程試圖執(zhí)行非法機器指令時,內(nèi)核發(fā)送此信號。默認操作是終止進程并生成一個核心轉(zhuǎn)儲。進程可以選擇捕獲并處理SIGILL,但它們的行為在發(fā)生后沒有定義。
  • SIGINT
    當用戶輸入中斷字符(通常為Ctrl-C)時,此信號被發(fā)送到前臺進程組中的所有進程。默認行為是終止;但是,進程可以選擇 捕捉和處理這個信號,通常在結(jié)束前進行清理。
  • SIGIO
    處理異步IO
  • SIGKILL
    這個信號是從kill()系統(tǒng)調(diào)用發(fā)送的;它的存在是為了向系統(tǒng)管理員提供一種絕對有效的方式來無條件地殺死一個進程。這個信號不能被捕獲或忽略,而且它結(jié)果總是終止進程。
  • SIGPIPE
    如果進程寫入管道,但讀取器已終止,則內(nèi)核將引發(fā)此信號。默認操作是終止進程,但是這個信號可能會被捕獲和處理。
  • SIGPROF
    當與ITIMER_PROF標志一起使用時,setitimer()函數(shù)將在分析計時器過期時生成此信號。默認操作是終止進程。
  • SIGPWR
    這個信號與系統(tǒng)有關(guān)。在linux上,它表示低電池狀態(tài)(例如在不間斷電源或UPS中)。UPS監(jiān)視守護進程將此信號發(fā)送給init,然后希望在電源斷電前完成系統(tǒng)的清理和關(guān)閉。
  • SIGQUIT
    當用戶提供終端退出字符(通常為Ctrl-)時,內(nèi)核會為前臺進程組中的所有進程發(fā)出此信號。默認操作是終止進程 生成一個core file。
  • SIGSEGV
    此信號的名稱源于分段沖突,當它嘗試無效的內(nèi)存訪問時,該信號被發(fā)送到進程。進程可以捕獲并處理此信號,但默認操作是終止進程并生成一個core dump。
  • SIGSTOP
    這個信號只由kill()發(fā)送。它無條件地停止一個進程,不能被捕獲或忽略。
  • SIGSYS
    內(nèi)核在試圖調(diào)用無效的系統(tǒng)調(diào)用時將此信號發(fā)送給進程。
  • SIGTERM
    此信號僅由kill()發(fā)送;它允許用戶優(yōu)雅地終止進程(默認操作)。進程可能會選擇在終止之前捕獲這個信號并清除,但被認為是粗魯?shù)刈プ∵@個信號而不立即終止。
  • SIGTRAP
    當內(nèi)核穿過斷點時,將此信號發(fā)送給進程。通常,調(diào)試器捕獲這個信號,而其他進程忽略它。
  • SIGTSTP
    當用戶提供掛起字符(通常是Ctrl-Z)時,內(nèi)核將此信號發(fā)送給前臺進程組中的所有進程。
  • SIGTTIN
    當試圖從其控制終端讀取時,該信號被發(fā)送到后臺的進程。默認操作是停止進程。
  • SIGTTOU
    當試圖寫入其控制終端時,該信號被發(fā)送到后臺的進程。默認操作是停止進程。
  • SIGURG
    當out-of-band(OOB)數(shù)據(jù)到達套接字上時,內(nèi)核將此信號發(fā)送給進程。帶外數(shù)據(jù)超出了本書的范圍。
  • SIGUSR1 and SIGUSR2
    這些信號可用于用戶定義的用途。默認操作是終止進程。
  • SIGVTALRM
    當使用ITIMER_VIRTUAL標志創(chuàng)建的計時器過期時,setitimer()函數(shù)將發(fā)送此信號。
  • SIGWINCH
    當前臺進程組中的所有進程的終端窗口大小發(fā)生變化時,內(nèi)核將引發(fā)此信號。默認情況下,進程忽略此信號,但它們可能選擇捕獲 如果他們知道終端的窗口大小,就處理它。一個程序捕捉這個信號很好的例子, 是top-嘗試調(diào)整其窗口時,它正在運行,并觀察它的反應。
  • SIGXCPU
    當進程超過其軟處理器限制時,內(nèi)核將引發(fā)此信號。內(nèi)核將繼續(xù)每秒發(fā)出一次此信號,直到進程退出或超過其硬處理器限制為止。 一旦超出了硬限制,內(nèi)核就會向進程發(fā)送SIGKILL。
  • SIGXFSZ
    當進程超過其文件大小限制時,內(nèi)核將引發(fā)此信號。默認操作是終止進程,但如果捕獲或忽略此信號,系統(tǒng)調(diào)用將返回-1,并設置errno-EFBIg。

基本信號管理

#include<signal.h>
typedef void(*sighandler_t)(int);
sighandler_t signal(int signo, sighandler_t handler);

還可以使用signal()指示內(nèi)核忽略當前進程的給定信號,或者將信號重置為默認行為。這是使用處理??梢酝ㄟ^使用特殊的值給予handler參數(shù)來是實現(xiàn)。

  • SIG_DEL
    設置signal的行為默認化。
  • SIG_IGN
    忽略此參數(shù)。

等待一個或任意信號

可用于調(diào)試和編寫演示代碼片段,POSIX定義的pause()系統(tǒng)調(diào)用將進程置于睡眠狀態(tài),直到接收到處理或終止進程的信號為止 :

#include <unistd.h>
int pause(void);

pause()只在接收到信號時返回,在這種情況下信號被處理,而pause()返回?1并將errno設置為EINTR。如果內(nèi)核引發(fā)一個被忽略的信號,進程就不會喚醒。

Examples

//test SIGINT
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/* handler for SIGINT */
static void sigint_handler (int signo) {
  /*
   * Technically, you shouldn't use printf() in a
   * signal handler, but it isn't the end of the
   * world. I'll discuss why in the section
   * "Reentrancy."
   */
    printf ("Caught SIGINT!\n");
    exit (EXIT_SUCCESS);
}
int main (void) {
    /*
     * Register sigint_handler as our signal handler
     * for SIGINT.
     */
     if (signal (SIGINT, sigint_handler) == SIG_ERR) {
     fprintf (stderr, "Cannot handle SIGINT!\n");
    exit (EXIT_FAILURE);
}
for (;;)
    pause ();
return 0;
 }
測試結(jié)果
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/* handler for SIGINT and SIGTERM */
static void signal_handler (int signo) {
    if (signo == SIGINT)
        printf ("Caught SIGINT!\n");
    else if (signo == SIGTERM)
        printf ("Caught SIGTERM!\n");
    else {
    /* this should never happen */
        fprintf (stderr, "Unexpected signal!\n");
        exit (EXIT_FAILURE);
    }
    exit (EXIT_SUCCESS);
}
int main (void) {
/*
 * Register signal_handler as our signal handler
 * for SIGINT.
 */
    if (signal (SIGINT, signal_handler) == SIG_ERR) {
        fprintf (stderr, "Cannot handle SIGINT!\n");
        exit (EXIT_FAILURE);
    }
/*
 * Register signal_handler as our signal handler
 * for SIGTERM.
 */
    if (signal (SIGTERM, signal_handler) == SIG_ERR) {
        fprintf (stderr, "Cannot handle SIGTERM!\n");
        exit (EXIT_FAILURE);
    }
/* Reset SIGPROF's behavior to the default. */
    if (signal (SIGPROF, SIG_DFL) == SIG_ERR) {
        fprintf (stderr, "Cannot reset SIGPROF!\n");
        exit (EXIT_FAILURE);
    }
/* Ignore SIGHUP. */
    if (signal (SIGHUP, SIG_IGN) == SIG_ERR) {
        fprintf (stderr, "Cannot ignore SIGHUP!\n");
        exit (EXIT_FAILURE);
    }
    for (;;)
        pause ();
    return 0; 
}

執(zhí)行和繼承

子進程繼承父進程的信號操作(ignore, default, handle)。


signal
/* handle SIGINT, but only if it isn't ignored */
if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
    if (signal (SIGINT, sigint_handler) == SIG_ERR)
        fprintf (stderr, "Failed to handle SIGINT!\n");
}
/* handle SIGQUIT, but only if it isn't ignored */
if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) {
    if (signal (SIGQUIT, sigquit_handler) == SIG_ERR)
        fprintf (stderr, "Failed to handle SIGQUIT!\n");
}

Mapping Signal Numbers to Strings

#define _GNU_SOURCE
#include <string.h>
char * strsignal (int signo);
static void signal_handler (int signo) {
    printf ("Caught %s\n", sys_siglist[signo]);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Unix/Linux的信號處理 信號(signal)就是Unix/Linux系統(tǒng)中最常見的一種軟件中斷的方式。中斷...
    vera姐姐閱讀 469評論 0 0
  • 信號(signal)是一種軟件中斷,它提供了一種處理異步事件的方法,也是進程間惟一的異步通信方式。在Linux系統(tǒng)...
    夏大王2019閱讀 1,072評論 0 1
  • 計算機系統(tǒng)漫游 代碼從文本到可執(zhí)行文件的過程(c語言示例):預處理階段,處理 #inlcude , #defin...
    willdimagine閱讀 3,835評論 0 5
  • 又來到了一個老生常談的問題,應用層軟件開發(fā)的程序員要不要了解和深入學習操作系統(tǒng)呢? 今天就這個問題開始,來談談操...
    tangsl閱讀 4,322評論 0 23
  • 在我3周歲那年,我媽病逝了,留下我們姐弟仨。我姐大我兩歲,我大我弟三歲,她是我和我弟的頂梁柱!雖是姐勝似媽。 20...
    春來燕回閱讀 188評論 0 1

友情鏈接更多精彩內(nèi)容