linux signal 详解

参考https://man7.org/linux/man-pages/man7/signal.7.html

signal是什么

定位

  • 进程间通信机制

作用

  • 给进程传递关键控制信息

用法

  • signal个数种类固定,确定对应信号的handler即可

谁产生的signal

也是改变程序状态的原因,主要以下三种

  • 用户在终端与程序交互

  • 程序异常

  • 系统调用

    • kill

      Sends a signal to a specified process, to all members of a specified process group, or to all processes on the system.

    • raise

      Sends a signal to the calling thread.

    • ...

各个信号的具体产生原因

Signal      Standard   Action   Comment

SIGABRT      P1990      Core    Abort signal from abort(3)
SIGALRM      P1990      Term    Timer signal from alarm(2)
SIGBUS       P2001      Core    Bus error (bad memory access)
SIGCHLD      P1990      Ign     Child stopped or terminated
SIGCLD         -        Ign     A synonym for SIGCHLD
SIGCONT      P1990      Cont    Continue if stopped
SIGEMT         -        Term    Emulator trap
SIGFPE       P1990      Core    Floating-point exception
SIGHUP       P1990      Term    Hangup detected on controlling terminal or death of controlling process
SIGILL       P1990      Core    Illegal Instruction
SIGINFO        -                A synonym for SIGPWR
SIGINT       P1990      Term    Interrupt from keyboard

SIGIO          -        Term    I/O now possible (4.2BSD)
SIGIOT         -        Core    IOT trap. A synonym for SIGABRT
SIGKILL      P1990      Term    Kill signal
SIGLOST        -        Term    File lock lost (unused)
SIGPIPE      P1990      Term    Broken pipe: write to pipe with no readers; see pipe(7)
SIGPOLL      P2001      Term    Pollable event (Sys V); synonym for SIGIO
SIGPROF      P2001      Term    Profiling timer expired
SIGPWR         -        Term    Power failure (System V)
SIGQUIT      P1990      Core    Quit from keyboard
SIGSEGV      P1990      Core    Invalid memory reference
SIGSTKFLT      -        Term    Stack fault on coprocessor (unused)
SIGSTOP      P1990      Stop    Stop process
SIGTSTP      P1990      Stop    Stop typed at terminal
SIGSYS       P2001      Core    Bad system call (SVr4); see also seccomp(2)
SIGTERM      P1990      Term    Termination signal
SIGTRAP      P2001      Core    Trace/breakpoint trap
SIGTTIN      P1990      Stop    Terminal input for background process
SIGTTOU      P1990      Stop    Terminal output for background process
SIGUNUSED      -        Core    Synonymous with SIGSYS
SIGURG       P2001      Ign     Urgent condition on socket (4.2BSD)
SIGUSR1      P1990      Term    User-defined signal 1
SIGUSR2      P1990      Term    User-defined signal 2
SIGVTALRM    P2001      Term    Virtual alarm clock (4.2BSD)
SIGXCPU      P2001      Core    CPU time limit exceeded (4.2BSD); see setrlimit(2)
SIGXFSZ      P2001      Core    File size limit exceeded (4.2BSD); see setrlimit(2)
SIGWINCH       -        Ign     Window resize signal (4.3BSD, Sun)

Real-time signals

范围

  • SIGRTMIN - SIGRTMAX 之间

特性

  • 全部隶属未定义信号,用于用户定义,默认终止程序

谁发给的进程

  • 产生信号的原因多样
  • 产生信号的主体多样
  • 发送信号给进程的主体确定,是在内核态操作系统发送的

什么时候发的

  • 时机确定:内核态 -> 进程用户态
    • 系统调用返回
    • 操作系统进程调度到该进程
  • 当内核态转变用户态,操作系统会检查是否有pending信号在队列
  • 信号处理在用户态处理
  • 若一次内核态到用户态的转变,产生多次某一标准信号,只会保留一次
  • 若一次内核态到用户态的转变,产生多个标准信号,则顺序未定义
  • 若一次内核态到用户态的转变,产生多次某一Real-time signals, 多次都会保留
  • 若一次内核态到用户态的转变,产生多个Real-time signals,则顺序由小到大发送给进程
  • 若一次内核态到用户态的转变,产生Real-time signals和标准信号,标准信号优先

如何处理signal

默认处理行为

Term   Default action is to terminate the process.
Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

用户可以自定义信号处理函数

如何自定义处理函数

注册自定义信号处理函数

#include <iostream>
#include <signal.h>
#include <unistd.h>

volatile bool s_quit = false;
void SignalHandler(int signal) {
    std::cout << "Receive signal : " << signal << "\n";
    if(signal == SIGINT) {
        std::cout << "Receive Ctrl + C!\n";
    } else if (signal == SIGRTMIN) {
        s_quit = true;
        std::cout << "Exit gracefully!\n";
    }
}

int main(int arg, char *args[]) {
    //注册信号
    signal(SIGINT, SignalHandler);
    signal(SIGRTMIN, SignalHandler);
    while (!s_quit) {
        sleep(1);
    }
    return 0;
}

volatile关键字

原因

  • 单一程序编译时,编译优化可能使得s_quit不总是访问内存值,由此可能出现不能及时捕获内存值变化

作用

  • 阻止编译优化,每次访问时访问内存,及时捕获值变化
posted @ 2021-06-08 23:31  Jamgun  阅读(482)  评论(0编辑  收藏  举报