在POSIX系统上,终止信号通常具有以下顺序(根据许多手册页和POSIX规范):
1.SIGTERM-礼貌地请求进程终止。它应该优雅地终止,清理所有资源(文件、套接字、子进程等),删除临时文件等。
1.SIGQUIT-更有力的请求。它应该终止不优雅,仍然清理绝对需要清理的资源,但可能不删除临时文件,可能会在某个地方写入调试信息;在某些系统上还会写入核心转储(无论信号是否被应用程序捕获)。
1.SIGKILL-最强烈的请求。进程甚至没有被要求做任何事情,但系统将清理进程,无论它喜欢与否。最有可能的是写入了核心转储。SIGINT
如何融入这幅图景呢?当用户点击CRTL+C
时,CLI进程通常由SIGINT
终止,但是也可以由SIGINT
使用KILL
实用程序终止后台进程。我在规范或头文件中看不到的是,SIGINT
是否比SIGTERM
更强大,或者SIGINT
和SIGTERM
之间是否有任何区别。
更新:
到目前为止,我找到的对终止信号的最佳描述是在GNU LibC Documentation中。它很好地解释了SIGTERM和SIGQUIT之间的有意区别。
它说的是SIGTERM
:
这是礼貌地要求程序终止的正常方式。
上面写着关于SIGQUIT
:
[.]并在终止进程时产生核心转储,就像程序错误信号一样。您可以将其视为被用户“检测到”的程序错误情况。[.]在处理SIGQUIT时最好省略某些类型的清理。例如,如果程序创建临时文件,它应该通过删除临时文件来处理其他终止请求。但SIGQUIT最好不要删除它们,这样用户就可以结合核心转储检查它们。
而SIGHUP
也得到了很好的解释。SIGHUP并不是一个真正的终止信号,它只是意味着与用户的“连接”已经丢失,因此应用程序不能期望用户读取任何进一步的输出(例如,stdout/stderr输出),并且不再期望用户输入。对于大多数应用程序来说,这意味着他们最好退出。理论上,应用程序还可以在收到SIGHUP时决定进入守护程序模式,现在作为后台进程运行,将输出写入配置的日志文件。对于大多数已在后台运行的守护进程,SIGHUP通常意味着它们将重新检查其配置文件,因此您可以在编辑配置文件后将其发送到后台进程。
然而,除了CRTL+C发送的SIGINT之外,该页面上没有对SIGINT进行有用的解释。有没有理由用不同于SIGTERM的方式来处理SIGINT?如果是这样的话,原因是什么,处理方式又有何不同?
6条答案
按热度按时间9udxz4iz1#
SIGTERM
和SIGKILL
用于通用*“终止此进程”*请求。SIGTERM
(默认)和SIGKILL
(始终)将导致进程终止。SIGTERM
可能会被进程捕获(例如,以便它可以根据自己的意愿进行清理),或者甚至完全被忽略;但是SIGKILL
不能被捕获或忽略。SIGINT
和SIGQUIT
专门用于来自终端的请求:可以指定特定的输入字符来生成这些信号(取决于终端控制设置)。SIGINT
的默认操作与SIGTERM
的默认操作和SIGKILL
的不可更改操作是相同类型的进程终止;SIGQUIT
的默认操作也是进程终止,但可能会发生其他实现定义的操作,如生成核心转储。如果需要,进程可以捕获或忽略它们。正如您所说,
SIGHUP
旨在指示终端连接已丢失,而不是作为终止信号。但是,同样,SIGHUP
的默认操作(如果进程没有捕获或忽略它)是以与SIGTERM
相同的方式终止进程,等等。POSIX的POSIX定义中有一个表,其中列出了各种信号及其默认操作和用途,General Terminal Interface一章包含了更多与终端相关的信号的详细信息。
0md85ypi2#
man 7 signal
这是您经常想要查看的Linux man-pages project的方便的非标准化手册页,以获取Linux信号信息。
版本3.22提到了一些有趣的事情,例如:
信号SIGKILL和SIGSTOP不能被捕获、阻止或忽略。
并包含该表:
其总结了例如区分SIGQUIT和SIGQUIT的信号M1n1O1p,因为SIGQUIT具有动作M1n2O1p和SIGINT M1n3O1p。
这些操作记录在同一文档中:
从内核的Angular 来看,我看不出SIGTERM和SIGINT之间有什么区别,因为两者都有操作
Term
,并且都可以被捕获。这似乎只是一种“常用惯例的区别”:kill
发送的默认信号有些信号是ANSI C,有些不是
一个相当大的区别是:
它们在C99 draft N1256的“7.14信号处理”一节中描述:
这使得SIGINT成为交互Ctrl+C的一个很好的候选者。
POSIX 7
POSIX 7使用
signal.h
标题记录信号:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html该页面还有下面的兴趣表,其中提到了我们在
man 7 signal
中已经看到的一些事情:BusyBox init
BusyBox的1.29.2默认
reboot
命令向进程发送SIGTERM,休眠一秒钟,然后发送SIGKILL。这似乎是不同发行版之间的普遍约定。使用以下命令关闭BusyBox系统时:
它向初始化进程发送信号。
然后,init信号处理程序结束调用:
它打印到终端:
这里有一个最小的具体例子。
内核发出的信号
c9x0cxw03#
正如黑暗尘埃所指出的,许多信号都有相同的结果,但进程可以通过区分每个信号是如何生成的来为它们附加不同的操作。查看FreeBSD内核源代码(kern_sig.c),我看到这两个信号以相同的方式处理,它们终止进程并被传递给任何线程。
7vhp5slm4#
在谷歌上快速搜索sigint vs sigterm后,似乎两者之间唯一有意的区别是它是由键盘快捷键启动的,还是通过显式调用
kill
启动的。因此,例如,您可以截取Sigint并对其进行特殊处理,因为您知道它很可能是通过键盘快捷键发送的。也许刷新屏幕之类的,而不是死掉(不推荐,因为人们预计
^C
会扼杀程序,这只是一个例子)。我还了解到
^
应该发送SigQuit,这样我就可以开始使用它了。看起来很有用。rkkpypqq5#
使用
kill
(系统调用和实用程序),只要您有权限,几乎可以向任何进程发送任何信号。进程无法区分信号是如何产生的,也无法区分是谁发出的。也就是说,
SIGINT
实际上是用来通知Ctrl-C
中断的,而SIGTERM
是一般的终端信号。没有信号更强的概念,唯一的例外是有一些信号无法阻止或处理(根据手册页的SIGKILL
和SIGSTOP
)。在接收进程如何处理信号(以及该信号的默认操作是什么)方面,一个信号只能比另一个信号“更强”。例如,默认情况下,
SIGTERM
和SIGINT
都会导致终止。但是如果忽略SIGTERM
,那么它不会终止您的进程,而SIGINT
仍然会。kwvwclae6#
除了少数信号外,信号处理程序可以捕获各种信号,或者可以修改接收信号时的默认行为。有关详细信息,请参阅
signal(7)
手册页。