SIGINT与其他终止信号(如SIGTERM、SIGQUIT和SIGKILL)有何关系?

dsf9zpds  于 2022-10-17  发布在  其他
关注(0)|答案(6)|浏览(296)

在POSIX系统上,终止信号通常具有以下顺序(根据许多手册页和POSIX规范):
1.SIGTERM-礼貌地请求进程终止。它应该优雅地终止,清理所有资源(文件、套接字、子进程等),删除临时文件等。
1.SIGQUIT-更有力的请求。它应该终止不优雅,仍然清理绝对需要清理的资源,但可能不删除临时文件,可能会在某个地方写入调试信息;在某些系统上还会写入核心转储(无论信号是否被应用程序捕获)。
1.SIGKILL-最强烈的请求。进程甚至没有被要求做任何事情,但系统将清理进程,无论它喜欢与否。最有可能的是写入了核心转储。
SIGINT如何融入这幅图景呢?当用户点击CRTL+C时,CLI进程通常由SIGINT终止,但是也可以由SIGINT使用KILL实用程序终止后台进程。我在规范或头文件中看不到的是,SIGINT是否比SIGTERM更强大,或者SIGINTSIGTERM之间是否有任何区别。

更新:

到目前为止,我找到的对终止信号的最佳描述是在GNU LibC Documentation中。它很好地解释了SIGTERM和SIGQUIT之间的有意区别。
它说的是SIGTERM
这是礼貌地要求程序终止的正常方式。
上面写着关于SIGQUIT
[.]并在终止进程时产生核心转储,就像程序错误信号一样。您可以将其视为被用户“检测到”的程序错误情况。[.]在处理SIGQUIT时最好省略某些类型的清理。例如,如果程序创建临时文件,它应该通过删除临时文件来处理其他终止请求。但SIGQUIT最好不要删除它们,这样用户就可以结合核心转储检查它们。
SIGHUP也得到了很好的解释。SIGHUP并不是一个真正的终止信号,它只是意味着与用户的“连接”已经丢失,因此应用程序不能期望用户读取任何进一步的输出(例如,stdout/stderr输出),并且不再期望用户输入。对于大多数应用程序来说,这意味着他们最好退出。理论上,应用程序还可以在收到SIGHUP时决定进入守护程序模式,现在作为后台进程运行,将输出写入配置的日志文件。对于大多数已在后台运行的守护进程,SIGHUP通常意味着它们将重新检查其配置文件,因此您可以在编辑配置文件后将其发送到后台进程。
然而,除了CRTL+C发送的SIGINT之外,该页面上没有对SIGINT进行有用的解释。有没有理由用不同于SIGTERM的方式来处理SIGINT?如果是这样的话,原因是什么,处理方式又有何不同?

9udxz4iz

9udxz4iz1#

SIGTERMSIGKILL用于通用*“终止此进程”*请求。SIGTERM(默认)和SIGKILL(始终)将导致进程终止。SIGTERM可能会被进程捕获(例如,以便它可以根据自己的意愿进行清理),或者甚至完全被忽略;但是SIGKILL不能被捕获或忽略。
SIGINTSIGQUIT专门用于来自终端的请求:可以指定特定的输入字符来生成这些信号(取决于终端控制设置)。SIGINT的默认操作与SIGTERM的默认操作和SIGKILL的不可更改操作是相同类型的进程终止;SIGQUIT的默认操作也是进程终止,但可能会发生其他实现定义的操作,如生成核心转储。如果需要,进程可以捕获或忽略它们。
正如您所说,SIGHUP旨在指示终端连接已丢失,而不是作为终止信号。但是,同样,SIGHUP的默认操作(如果进程没有捕获或忽略它)是以与SIGTERM相同的方式终止进程,等等。
POSIXPOSIX定义中有一个表,其中列出了各种信号及其默认操作和用途,General Terminal Interface一章包含了更多与终端相关的信号的详细信息。

0md85ypi

0md85ypi2#

man 7 signal

这是您经常想要查看的Linux man-pages project的方便的非标准化手册页,以获取Linux信号信息。
版本3.22提到了一些有趣的事情,例如:
信号SIGKILL和SIGSTOP不能被捕获、阻止或忽略。
并包含该表:

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

其总结了例如区分SIGQUIT和SIGQUIT的信号M1n1O1p,因为SIGQUIT具有动作M1n2O1p和SIGINT M1n3O1p。
这些操作记录在同一文档中:

  1. The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:
  2. Term Default action is to terminate the process.
  3. Ign Default action is to ignore the signal.
  4. Core Default action is to terminate the process and dump core (see core(5)).
  5. Stop Default action is to stop the process.
  6. Cont Default action is to continue the process if it is currently stopped.

从内核的Angular 来看,我看不出SIGTERM和SIGINT之间有什么区别,因为两者都有操作Term,并且都可以被捕获。这似乎只是一种“常用惯例的区别”:

  • SIGINT是从终端执行CTRL-C时发生的情况
  • SIGTERM是kill发送的默认信号
    有些信号是ANSI C,有些不是

一个相当大的区别是:

  • SIGINT和SIGTERM为ANSI C,因此更便携
  • SIGQUIT和SIGKILL不是

它们在C99 draft 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中已经看到的一些事情:

  1. Signal Default Action Description
  2. SIGABRT A Process abort signal.
  3. SIGALRM T Alarm clock.
  4. SIGBUS A Access to an undefined portion of a memory object.
  5. SIGCHLD I Child process terminated, stopped,
  6. SIGCONT C Continue executing, if stopped.
  7. SIGFPE A Erroneous arithmetic operation.
  8. SIGHUP T Hangup.
  9. SIGILL A Illegal instruction.
  10. SIGINT T Terminal interrupt signal.
  11. SIGKILL T Kill (cannot be caught or ignored).
  12. SIGPIPE T Write on a pipe with no one to read it.
  13. SIGQUIT A Terminal quit signal.
  14. SIGSEGV A Invalid memory reference.
  15. SIGSTOP S Stop executing (cannot be caught or ignored).
  16. SIGTERM T Termination signal.
  17. SIGTSTP S Terminal stop signal.
  18. SIGTTIN S Background process attempting read.
  19. SIGTTOU S Background process attempting write.
  20. SIGUSR1 T User-defined signal 1.
  21. SIGUSR2 T User-defined signal 2.
  22. SIGTRAP A Trace/breakpoint trap.
  23. SIGURG I High bandwidth data is available at a socket.
  24. SIGXCPU A CPU time limit exceeded.
  25. SIGXFSZ A File size limit exceeded.

BusyBox init

BusyBox的1.29.2默认reboot命令向进程发送SIGTERM,休眠一秒钟,然后发送SIGKILL。这似乎是不同发行版之间的普遍约定。
使用以下命令关闭BusyBox系统时:

  1. reboot

它向初始化进程发送信号。
然后,init信号处理程序结束调用:

  1. static void run_shutdown_and_kill_processes(void)
  2. {
  3. /* Run everything to be run at "shutdown". This is done _prior_
  4. * to killing everything, in case people wish to use scripts to
  5. * shut things down gracefully... */
  6. run_actions(SHUTDOWN);
  7. message(L_CONSOLE | L_LOG, "The system is going down NOW!");
  8. /* Send signals to every process _except_ pid 1 */
  9. kill(-1, SIGTERM);
  10. message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
  11. sync();
  12. sleep(1);
  13. kill(-1, SIGKILL);
  14. message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
  15. sync();
  16. /*sleep(1); - callers take care about making a pause */
  17. }

它打印到终端:

  1. The system is going down NOW!
  2. Sent SIGTERM to all processes
  3. Sent SIGKILL to all processes

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

内核发出的信号

  • 签名:
  • OOM杀手:什么是Linux内存管理中的RSS和VSZ
展开查看全部
c9x0cxw0

c9x0cxw03#

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

  1. SA_KILL|SA_PROC, /* SIGINT */
  2. SA_KILL|SA_PROC, /* SIGTERM */
7vhp5slm

7vhp5slm4#

在谷歌上快速搜索sigint vs sigterm后,似乎两者之间唯一有意的区别是它是由键盘快捷键启动的,还是通过显式调用kill启动的。
因此,例如,您可以截取Sigint并对其进行特殊处理,因为您知道它很可能是通过键盘快捷键发送的。也许刷新屏幕之类的,而不是死掉(不推荐,因为人们预计^C会扼杀程序,这只是一个例子)。
我还了解到^应该发送SigQuit,这样我就可以开始使用它了。看起来很有用。

rkkpypqq

rkkpypqq5#

使用kill(系统调用和实用程序),只要您有权限,几乎可以向任何进程发送任何信号。进程无法区分信号是如何产生的,也无法区分是谁发出的。
也就是说,SIGINT实际上是用来通知Ctrl-C中断的,而SIGTERM是一般的终端信号。没有信号更强的概念,唯一的例外是有一些信号无法阻止或处理(根据手册页的SIGKILLSIGSTOP)。
在接收进程如何处理信号(以及该信号的默认操作是什么)方面,一个信号只能比另一个信号“更强”。例如,默认情况下,SIGTERMSIGINT都会导致终止。但是如果忽略SIGTERM,那么它不会终止您的进程,而SIGINT仍然会。

kwvwclae

kwvwclae6#

除了少数信号外,信号处理程序可以捕获各种信号,或者可以修改接收信号时的默认行为。有关详细信息,请参阅signal(7)手册页。

相关问题