SIGINT如何与其他终止信号如SIGTERM、SIGQUIT和SIGKILL相关联?

16 浏览
0 Comments

SIGINT如何与其他终止信号如SIGTERM、SIGQUIT和SIGKILL相关联?

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

  1. SIGTERM - 礼貌地请求进程终止。它应该优雅地终止,清理所有资源(文件,套接字,子进程等),删除临时文件等。
  2. SIGQUIT - 更强有力的请求。它应该优雅地终止,仍然清理需要清理的所有资源,但可能不会删除临时文件,可能在某些系统上将调试信息写入某个位置;在某些系统上,还会写入核心转储(无论信号是否被应用程序捕获)。
  3. SIGKILL - 最强有力的请求。甚至都没有要求进程执行任何操作,但系统将清理进程,无论它是否喜欢这样做。最有可能写入核心转储。

SIGINT在这种情况下如何适应呢?当用户按下CRTL+C时,CLI进程通常会被SIGINT终止,但是后台进程也可以使用KILL实用程序使用SIGINT终止。我在规范或标头文件中看不到SIGINT是否比SIGTERM更强有力,或者SIGINTSIGTERM之间是否有任何区别。

更新:

我迄今为止发现的关于终止信号的最好描述在GNU LibC文档中。它很好地解释了SIGTERMSIGQUIT之间的区别。

它讲了关于SIGTERM的内容:

这是一种礼貌地请求程序停止运行的常规方式。

它也提到了SIGQUIT

[...]当进程终止时,它会生成一个核心转储文件,就像程序错误信号一样。

你可以将其视为用户“检测到”的程序错误条件。[...]在处理SIGQUIT时,最好不要进行某些清理操作。

例如,如果程序创建临时文件,则应通过删除临时文件来处理其他终止请求。但最好不要在处理SIGQUIT时删除它们,以便用户可以与核心转储文件一起查看它们。

关于SIGHUP也有足够的解释。SIGHUP并不是真正的终止信号,它只是意味着与用户的“连接”已丢失,因此应用程序不能期望用户继续阅读任何输出(例如stdout/stderr输出),也不再期望从用户那里收到任何输入。对于大多数应用程序来说,这意味着它们最好退出。理论上,当收到SIGHUP时,一个应用程序也可以决定进入守护进程模式,现在作为后台进程运行,将输出写入配置的日志文件。对于正在后台运行的大多数守护程序,SIGHUP通常意味着它们应该重新检查其配置文件,因此在编辑配置文件后向后台进程发送SIGHUP。

然而,这个页面没有关于SIGINT的有用解释,除了它是由CRTL+C发送的。有没有任何理由在处理SIGINT时与处理SIGTERM不同?如果是这样,处理方式会有何区别?

admin 更改状态以发布 2023年5月21日
0
0 Comments

man 7 signal

这是Linux man-pages项目中方便的非规范手册,你经常需要查看以获取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

它总结了具有不同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.

从内核的角度来看,我看不出SIGTERM和SIGINT之间的区别,因为它们都有Term操作,并且都可以被捕获。看起来这只是一个“通用使用惯例的区别”:

  • SIGINT是从终端执行CTRL-C时发生的
  • 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.

BusyBox init

BusyBox 1.29.2默认的reboot命令向进程发送SIGTERM信号,等待一秒,然后发送SIGKILL信号。这似乎是不同发行版之间的一种普遍惯例。

当你使用下面的命令关机BusyBox系统:

reboot

它向init进程发送信号。

然后,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 */
}

它在终端上输出:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

这里有一个最小的具体例子

内核发送的信号

0
0 Comments

SIGTERMSIGKILL是通用的"终止此进程"请求。默认情况下,SIGTERMSIGKILL都会导致进程终止。进程可以捕获SIGTERM(例如,如果它想要自己进行清理),甚至可以完全忽略它;但是SIGKILL无法被捕获或忽略。

SIGINTSIGQUIT特别用于来自终端的请求:可以分配特定的输入字符来生成这些信号(取决于终端控制设置)。默认情况下,SIGINT的操作方式与SIGTERM的默认操作方式相同,而SIGQUIT的不可更改操作方式也是进程终止,但是可能会发生其他实现定义的操作,例如生成核心转储。如果需要,进程可以捕获或忽略任何信号。

SIGHUP,正如您所说,旨在指示终端连接已丢失,而不是作为终止信号。但是,再次说明,如果进程不捕获或忽略它,则SIGHUP的默认操作是以与SIGTERM相同的方式终止进程。

POSIX定义中有一张表格,其中列出了各种信号及其默认操作和目的;General Terminal Interface章节包括有关终端相关信号的更多信息。

0