SIGINT如何与其他终止信号相关?

Mec*_*cki 95 unix linux posix

在POSIX系统上,终止信号通常具有以下顺序(根据许多MAN页面和POSIX规范):

  1. SIGTERM - 礼貌地要求进程终止.它将正常终止,清理所有资源(文件,套接字,子进程等),删除临时文件等.

  2. SIGQUIT - 更有力的请求.它应该终止不正常,仍然清理绝对需要清理的资源,但可能不会删除临时文件,可能会在某处写入调试信息; 在某些系统上也会写入核心转储(无论信号是否被应用程序捕获).

  3. SIGKILL - 最有力的要求.甚至没有要求该过程做任何事情,但系统将清理过程,无论是否喜欢.最有可能是编写核心转储.

SIGINT如何适应这张照片?当用户点击CRTL + C时,CLI进程通常由SIGINT终止,但是后台进程也可以由SIGINT使用KILL实用程序终止.我在规范或头文件中看不到的是SIGINT是否比SIGTERM更强或更强,或者SIGINT和SIGTERM之间有任何区别.

更新:

到目前为止,我发现的终止信号的最佳描述是在GNU LibC文档中.它很好地解释了SIGTERM和SIGQUIT之间存在预期的区别.

它说关于SIGTERM:

这是礼貌地要求程序终止的正常方式.

它说关于SIGQUIT:

[...]并在终止进程时生成核心转储,就像程序错误信号一样.您可以将此视为用户"检测到"的程序错误情况.[...]在处理SIGQUIT时最好省略某些类型的清理.例如,如果程序创建临时文件,它应该通过删除临时文件来处理其他终止请求.但是SIGQUIT最好不要删除它们,以便用户可以与核心转储一起检查它们.

而SIGHUP也解释得很好.SIGHUP实际上不是终止信号,它只是意味着用户的"连接"已经丢失,因此应用程序不能指望用户读取任何进一步的输出(例如stdout/stderr输出),并且没有输入可以从用户不再.对于大多数意味着他们退出的应用程序.从理论上讲,应用程序还可以决定在收到SIGHUP时进入守护进程模式,现在作为后台进程运行,将输出写入已配置的日志文件.对于已经在后台运行的大多数守护进程,SIGHUP通常意味着他们将重新检查其配置文件,因此您在编辑配置文件后将其发送到后台进程.

但是,除了CRTL + C发送的SIGINT之外,此页面上没有有用的SIGINT解释.是否有理由以不同于SIGTERM的方式处理SIGINT?如果是这样,那将是什么原因以及如何处理不同?

Mat*_*ery 76

SIGTERM和SIGKILL旨在用于通用"终止此过程"请求.SIGTERM(默认情况下)和SIGKILL(始终)将导致进程终止.SIGTERM可能被进程捕获(例如,如果它想要它可以进行自己的清理),甚至完全忽略; 但SIGKILL无法被捕获或忽略.

SIGINT和SIGQUIT专门用于来自终端的请求:可以分配特定的输入字符来生成这些信号(取决于终端控制设置).SIGINT的默认操作是与SIGTERM的默认操作和SIGKILL的不可更改操作相同的进程终止; SIGQUIT的默认操作也是进程终止,但可能会发生其他实现定义的操作,例如生成核心转储.如果需要,可以通过该过程捕获或忽略.

正如您所说,SIGHUP旨在表明终端连接已丢失,而不是终止信号.但是,同样,SIGHUP的默认操作(如果进程没有捕获或忽略它)是以与SIGTERM等相同的方式终止进程.

POSIX定义中有一个表,signal.h其中列出了各种信号及其默认操作和用途," 通用终端接口"一章中包含有关终端相关信号的更多详细信息.

  • 这是关键点:当程序运行时,可以使用单个字符从终端生成SIGINT和SIGQUIT.其他信号必须以某种方式由另一个程序生成(例如通过kill命令).SIGINT不如SIGQUIT暴力; 后者产生核心转储.SIGKILL无法被困.如果您的连接挂断(窗口关闭等),则会生成SIGHUP.所以,它们都有不同的含义. (8认同)
  • 看起来规格不是很精确,但我的理解是 SIGint 要求程序停止它的当前操作,而不一定是退出。对于设计为每次运行只执行一个操作的程序,这意味着退出,但对于具有某种 read-eval-print 循环的交互式程序,这可能意味着放弃当前的 eval 并返回读取用户输入。我认为在 sigint 上很少这样做。 (3认同)
  • @bdsl 谢谢,伙计。我查了半个网,终于找到你的评论了。正是你所说的,我已经用“ftp”检查过 - 这是一个交互式程序,当输入“open hostname”时,程序可能会阻塞,并且按抄送仅停止此“open”操作,而不是整个程序!此外,应该清楚的是,这只是程序的一个提示:其他程序可能不会以相同的方式运行,但在我看来,它们应该像“ftp”一样处理这些信号,因为这是使事情可预测的良好编程实践。伙计们,为 bdsl 的评论投票吧! (2认同)

Dio*_*lis 9

正如DarkDust所指出的,许多信号具有相同的结果,但是过程可以通过区分每个信号的生成方式来为它们附加不同的动作.查看FreeBSD内核源代码(kern_sig.c),我看到两个信号以相同的方式处理,它们终止进程并传递给任何线程.

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */
Run Code Online (Sandbox Code Playgroud)


Jon*_*han 8

在快速Google搜索sigint与sigterm之后,看起来两者之间的唯一预期差异是它是由键盘快捷键还是通过显式调用启动的kill.

因此,您可以,例如,拦截sigint并对其执行一些特殊操作,因为它知道它可能是通过键盘快捷方式发送的.也许刷新屏幕或其他东西,而不是死亡(不推荐,因为人们期望^C杀死程序,只是一个例子).

我还了解到^\应该发送sigquit,我可以自己开始使用它.看起来非常有用.


Cir*_*四事件 8

man 7 signal

这是您经常希望查看Linux信号信息的Linux手册页项目的便捷非规范手册页

版本3.22提到了一些有趣的事情,例如:

无法捕获,阻止或忽略信号SIGKILL和SIGSTOP。

并包含表:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process
Run Code Online (Sandbox Code Playgroud)

总结Action了区分SIGQUIT和SIGQUIT的信号,因为SIGQUIT具有动作Core和SIGINT Term

这些动作记录在同一文档中:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

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 (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.
Run Code Online (Sandbox Code Playgroud)

从内核的角度来看,我看不到SIGTERM和SIGINT之间的任何区别,因为两者都有作用Term并且都可以被捕获。看来这只是“常用用法约定的区别”:

  • 从终端执行CTRL-C时会发生SIGINT
  • SIGTERM是发送的默认信号 kill

有些信号是ANSI C,有些则不是

很大的区别是:

  • SIGINT和SIGTERM是ANSI C,因此更具可移植性
  • SIGQUIT和SIGKILL不是

它们在C99草案N1256的 “ 7.14信号处理”部分中进行了介绍

  • SIGINT收到交互式注意信号
  • SIGTERM将终止请求发送到程序

这使SIGINT成为交互式Ctrl + C的不错选择。

POSIX 7

POSIX 7的signal.h标头记录了信号:https : //pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

该页面还具有以下感兴趣的表格,其中提到了我们已经在其中看到的一些内容man 7 signal

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.
Run Code Online (Sandbox Code Playgroud)

BusyBox初始化

BusyBox的1.29.2默认reboot命令将SIGTERM发送到进程,休眠一秒钟,然后发送SIGKILL。这似乎是不同发行版之间的通用约定。

当您通过以下方式关闭BusyBox系统时:

reboot
Run Code Online (Sandbox Code Playgroud)

它向初始化进程发送信号。

然后,init信号处理程序最终调用:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}
Run Code Online (Sandbox Code Playgroud)

打印到终端:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Run Code Online (Sandbox Code Playgroud)

这是一个最小的具体示例

内核发送的信号