[Q-3]是否terminate
我的示例中的变量必须是volatile
?我有
见过很多这个变量是易失性的例子,还有一些例子
它不是。
旗帜terminate
应该volatile sig_atomic_t
:
因为处理函数可以异步调用。也就是说,处理程序可能会在程序中的任何点被调用,这是不可预测的。如果两个信号在很短的时间间隔内到达,则一个处理程序可以在另一个处理程序内运行。声明被认为是更好的做法volatile sig_atomic_t
,这种类型总是以原子方式访问,避免中断访问变量的不确定性。volatile
告诉编译器不要优化并将其放入寄存器。 (读:原子数据访问和信号处理 http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358详细说明)。
再来一张参考资料:24.4.7 原子数据访问和信号处理 http://www.gnu.org/software/libc/manual/html_node/Atomic-Data-Access.html#Atomic-Data-Access。
此外,7.14.1.1-5 中的 C11 标准表明,只有volatile sig_atomic_t
可以从信号处理程序访问(访问其他信号处理程序具有未定义的行为)。
[Q-4]我读过signal()
现已弃用,并使用sigaction()
。是
有任何非常好的例子来展示如何从
以前的signal()
称呼?我对新结构遇到了麻烦
我必须创建/传递以及它们如何组合在一起。
下面的示例(以及评论中的链接)可能会有所帮助:
// 1. Prepare struct
struct sigaction sa;
sa.sa_handler = sighandler;
// 2. To restart functions if interrupted by handler (as handlers called asynchronously)
sa.sa_flags = SA_RESTART;
// 3. Set zero
sigemptyset(&sa.sa_mask);
/* 3b.
// uncomment if you wants to block
// some signals while one is executing.
sigaddset( &sa.sa_mask, SIGINT );
*/
// 4. Register signals
sigaction( SIGINT, &sa, NULL );
参考:
-
Linux 编程入门,第四版 http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358:在这本书中,您的代码的解释是
sigaction()
“第 11 章:进程和信号”中有很好的说明。
- The 签名操作文档 http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/s/sigaction.html,包括一个示例(快速学习)。
- The GNU C Library: Signal Handling http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC330
*I started from 1 http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358, Presently I am reading 3 http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC358 GNU-library
[Q-5]第二次致电是signal()
必要的?有没有类似的事情我需要关心sigaction()
?
我不清楚为什么在程序终止之前将其设置为默认操作。我想下面这段话会给你答案:
处理信号 http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr1/z1ling.htm
对 signal 的调用仅建立信号处理one信号的发生。在调用信号处理函数之前,库会重置信号,以便在再次发生相同信号时执行默认操作。重置信号处理有助于防止无限循环,例如,如果在信号处理程序中执行的操作再次引发相同的信号。如果您希望每次发生信号时都将处理程序用于信号,则必须在处理程序中调用 signal 来恢复它。您应该谨慎恢复信号处理。例如,如果您不断恢复SIGINT
处理,您可能会失去中断和终止程序的能力。
The signal()
函数仅定义下一个接收到的信号的处理程序,之后恢复默认处理程序。所以信号处理程序需要调用signal()
如果程序需要继续使用非默认处理程序处理信号。
阅读讨论以供进一步参考:何时重新启用信号处理程序 http://cboard.cprogramming.com/linux-programming/150239-when-re-enable-signal-handlers.html.
[Q-1a]是否需要任何信号处理?
是的,Linux 会为你做清理工作。例如,如果您不关闭文件或套接字,Linux 将在进程终止后进行清理。但Linux可能不需要立即执行清理,可能需要一些时间(可能是为了保持系统高性能或其他一些问题)。例如,如果您不关闭 tcp-socket 并且程序终止,则内核不会立即关闭套接字以确保所有数据已传输,如果可能,TCP 会保证传输。
[Q-1b]因此,我可以用无限循环替换信号处理程序,让操作系统优雅地退出线程、取消分配内存等吗?
不,操作系统仅在程序终止后执行清理工作。当进程执行时,分配给该进程的资源不会被操作系统占用。 (操作系统无法知道你的进程是否处于无限循环中 -这是一个无法解决的问题 https://en.wikipedia.org/wiki/Halting_problem)。如果您希望在进程终止后操作系统为您执行清理操作,那么您不需要处理信号(即使您的进程被信号异常终止)。
[Q] All I'm trying to accomplish to to have my: main loop run until either ctrlc or power is disconnected or something really bad happens.
不,有一个限制!您无法捕获所有信号。有些信号无法捕获,例如SIGKILL
and SIGSTOP
两者都是终止信号。引用一则:
— 宏:intSIGKILL http://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
The SIGKILL
信号用于导致程序立即终止。它无法处理或忽略,因此总是致命的。也是not可以阻止该信号。
所以你不能使不可中断的程序(不间断的程序) https://stackoverflow.com/questions/12437648/uninterruptable-process-in-windowsor-linux!
I am not sure but may be you can do something like this in Windows systems: by writing TSRs (some sort of kernel-mode hooking). I remember from my thesis time that some viruses couldn't be terminated even from task manager but I also believe that they trick user by admin permissions.
我希望这个答案能帮助你。