【问题标题】:Can signal-handling be used to print intermediate results [closed]可以使用信号处理来打印中间结果吗[关闭]
【发布时间】:2018-06-24 00:34:40
【问题描述】:

我经常运行运行几天的程序,测试各种标准的连续整数。我想知道一个程序的进度,所以我通常让它打印出一条消息,比如每 100000000 次试验,但如果我可以通过向程序发送信号来获得中间结果,那就太好了。我想到的事情是这样的:

Create signal handler to print out value of n and resume in loop

Register signal handler
n=1
while( 1 ) {
    If n fits some criterion, print n
    n++
}

我的想法是我可以使用kill -SIGTYPE processid 来获得中间结果。有可能做我想做的事吗?如果是这样,怎么办?我看到的在 C 中使用信号处理的例子似乎都是在处理完信号后立即退出,而不是从信号被捕获的地方恢复。

【问题讨论】:

  • "在处理完信号后立即退出" 取决于您的使用情况,例如sigaction() ...当然可以做你想做的事。只是不要从信号处理程序内部打印,而是使用标志 (volatile sig_atomic_t)。
  • 我敢打赌你错过了这个one
  • 在哪个操作系统上?纯标准 C11 对信号是什么以及可以做什么的定义很差。
  • 你在写什么样的程序?请编辑您的问题以改进它(激励它,提供更多细节)。
  • 没有更多细节:你在什么操作系统上编码?什么样的应用程序? ...您的问题不清楚。

标签: c signals


【解决方案1】:

不(原则上),您不应该从信号处理程序调用printffputs(等等...),并且在Linux 上记录了此限制,请参阅signal(7)signal-safety(7)。花点时间了解异步信号安全函数的概念(您可以从信号处理程序内部调用的唯一函数——即使是间接调用——无需undefined behavior)。

(我猜你是在 Linux 上,或者至少在一些 POSIX 或类 Unix 系统上)

但是,有一种常用的方法可以克服这个问题:在信号处理程序中设置一些 volatile sig_atomic_t 标志,并在程序主循环中定期测试该标志。

另一种可能性是设置(使用pipe(2)),在初始化时,将pipe(7) 设置为self,并有一个信号处理程序,write(2)-s 一个或几个字节进入该管道(注意write(2) 是异步信号安全的,但 fprintfmalloc 不是)。您的event loop 将检查(使用poll(2))该管道的可读性,并在可能的情况下检查read(2)。这种常见的技巧经常被记录在案,例如in Qt.

请注意,signal 处理实际上是特定于操作系统的(例如,在 Linux 和 Windows 上不同),并且在各种 POSIX / Unix 系统中具有一些共同行为。

对于运行几天的程序,您可能希望它们也处理SIGTERM。然后,您可以保存一些persistent 状态(例如,在一些database 中,在一个文件中,可能使用sqlitegdbm)并能够从这种保存状态重新启动。阅读application checkpointing。您可能应该考虑在程序设计的早期保存(并能够从中重新启动)程序的状态。也许您会使用time(7) 设施来保存,例如每小时查看一次程序的状态(查看setitimer(2)alarm(2)SIGALRM 等...)。

【讨论】:

  • 非常感谢所有回复的人。 @Guarav 的评论特别有用,我标记为正确的答案也是如此。
猜你喜欢
  • 1970-01-01
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 2015-01-15
相关资源
最近更新 更多