信号#1

信号的概念

取决于进程的要求,内核对Signal信号有如下三种行为:

  1. 忽略信号
  2. 抓住这个信号并且对这个信号进行处理
  3. 采取默认行为

信号标识符Signal Identifiers

Signals#1

Signals#2

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

  • SIGABRT
    函数abort将此信号发送给调用它的进程。然后,该进程终止并生成一个core file。在Linux中,在条件不满足时,断言assert()调用abort() 。
  • SIGALRM
    alarm()和setitimer()函数(带有ITIMER_REAL标志)将此信号发送给在警报过期时调用它们的进程。
  • SIGBUS
    当进程发生内存保护(这个会出发SIGSEGV)以外的硬件故障时,内核会引发此信号。
  • SIGCHLD
    每当进程终止或停止时,内核都会向进程的父进程发送此信号。由于默认情况下忽略SIGCHLD, 所以进程必须显式的捕获并处理他们感兴趣的子进程。此信号的处理程序通常调用wait()。
  • SIGCONT
    当进程在停止后恢复时,内核将此信号发送给进程。默认情况下,此信号将被忽略,但如果进程希望在继续之后进行一个特殊的行为则可以抓住他。此信号通常由希望刷新屏幕的终端或编辑器使用。
  • SIGFPE
    此信号表示任何算术异常,而不仅仅是那些与浮点操作相关的异常。
  • SIGHUP
    当会话session的终端断开时,内核将此信号发送给会话领导人seesion leader。
  • SIGILL
    当进程试图执行非法机器指令时,内核发送此信号。默认操作是终止进程并生成一个核心转储。进程可以选择捕获并处理SIGILL,但它们的行为在发生后没有定义。
  • SIGINT
    当用户输入中断字符(通常为Ctrl-C)时,此信号被发送到前台进程组中的所有进程。默认行为是终止;但是,进程可以选择 捕捉和处理这个信号,通常在结束前进行清理。
  • SIGIO
    处理异步IO
  • SIGKILL
    这个信号是从kill()系统调用发送的;它的存在是为了向系统管理员提供一种绝对有效的方式来无条件地杀死一个进程。这个信号不能被捕获或忽略,而且它结果总是终止进程。
  • SIGPIPE
    如果进程写入管道,但读取器已终止,则内核将引发此信号。默认操作是终止进程,但是这个信号可能会被捕获和处理。
  • SIGPROF
    当与ITIMER_PROF标志一起使用时,setitimer()函数将在分析计时器过期时生成此信号。默认操作是终止进程。
  • SIGPWR
    这个信号与系统有关。在linux上,它表示低电池状态(例如在不间断电源或UPS中)。UPS监视守护进程将此信号发送给init,然后希望在电源断电前完成系统的清理和关闭。
  • SIGQUIT
    当用户提供终端退出字符(通常为Ctrl-)时,内核会为前台进程组中的所有进程发出此信号。默认操作是终止进程 生成一个core file。
  • SIGSEGV
    此信号的名称源于分段冲突,当它尝试无效的内存访问时,该信号被发送到进程。进程可以捕获并处理此信号,但默认操作是终止进程并生成一个core dump。
  • SIGSTOP
    这个信号只由kill()发送。它无条件地停止一个进程,不能被捕获或忽略。
  • SIGSYS
    内核在试图调用无效的系统调用时将此信号发送给进程。
  • SIGTERM
    此信号仅由kill()发送;它允许用户优雅地终止进程(默认操作)。进程可能会选择在终止之前捕获这个信号并清除,但被认为是粗鲁地抓住这个信号而不立即终止。
  • SIGTRAP
    当内核穿过断点时,将此信号发送给进程。通常,调试器捕获这个信号,而其他进程忽略它。
  • SIGTSTP
    当用户提供挂起字符(通常是Ctrl-Z)时,内核将此信号发送给前台进程组中的所有进程。
  • SIGTTIN
    当试图从其控制终端读取时,该信号被发送到后台的进程。默认操作是停止进程。
  • SIGTTOU
    当试图写入其控制终端时,该信号被发送到后台的进程。默认操作是停止进程。
  • SIGURG
    当out-of-band(OOB)数据到达套接字上时,内核将此信号发送给进程。带外数据超出了本书的范围。
  • SIGUSR1 and SIGUSR2
    这些信号可用于用户定义的用途。默认操作是终止进程。
  • SIGVTALRM
    当使用ITIMER_VIRTUAL标志创建的计时器过期时,setitimer()函数将发送此信号。
  • SIGWINCH
    当前台进程组中的所有进程的终端窗口大小发生变化时,内核将引发此信号。默认情况下,进程忽略此信号,但它们可能选择捕获 如果他们知道终端的窗口大小,就处理它。一个程序捕捉这个信号很好的例子, 是top-尝试调整其窗口时,它正在运行,并观察它的反应。
  • SIGXCPU
    当进程超过其软处理器限制时,内核将引发此信号。内核将继续每秒发出一次此信号,直到进程退出或超过其硬处理器限制为止。 一旦超出了硬限制,内核就会向进程发送SIGKILL。
  • SIGXFSZ
    当进程超过其文件大小限制时,内核将引发此信号。默认操作是终止进程,但如果捕获或忽略此信号,系统调用将返回-1,并设置errno-EFBIg。

基本信号管理

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

还可以使用signal()指示内核忽略当前进程的给定信号,或者将信号重置为默认行为。这是使用处理。可以通过使用特殊的值给予handler参数来是实现。

  • SIG_DEL
    设置signal的行为默认化。
  • SIG_IGN
    忽略此参数。

等待一个或任意信号

可用于调试和编写演示代码片段,POSIX定义的pause()系统调用将进程置于睡眠状态,直到接收到处理或终止进程的信号为止 :

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

pause()只在接收到信号时返回,在这种情况下信号被处理,而pause()返回−1并将errno设置为EINTR。如果内核引发一个被忽略的信号,进程就不会唤醒。

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;
 }
测试结果
#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; 
}

执行和继承

子进程继承父进程的信号操作(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]);
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容

  • Unix/Linux的信号处理 信号(signal)就是Unix/Linux系统中最常见的一种软件中断的方式。中断...
    vera姐姐阅读 378评论 0 0
  • 信号(signal)是一种软件中断,它提供了一种处理异步事件的方法,也是进程间惟一的异步通信方式。在Linux系统...
    夏大王2019阅读 997评论 0 1
  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,571评论 0 5
  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,105评论 0 23
  • 在我3周岁那年,我妈病逝了,留下我们姐弟仨。我姐大我两岁,我大我弟三岁,她是我和我弟的顶梁柱!虽是姐胜似妈。 20...
    春来燕回阅读 151评论 0 1