可以使用信号处理来打印中间结果

时间:2018-01-15 11:22:52

标签: c signals

我经常运行运行了几天的程序,测试各种标准的连续整数。我想知道一个程序在哪里,所以我通常每次打印一条消息,比如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中使用信号处理的例子似乎都在处理完信号之后立即退出,而不是从捕获信号的点恢复。

1 个答案:

答案 0 :(得分:3)

否(原则上),您不应该从信号处理程序中调用printffputs(etc ...),并且在Linux上记录此限制,请参阅signal(7)signal-safety(7)。花点时间了解 async-signal safe 函数的概念(你可以从信号处理程序中调用的唯一函数 - 即使是间接函数 - 没有undefined behavior)。

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

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

另一种可能性是在初始化时设置(使用pipe(2)),将pipe(7)设置为self,并设置一个write(2) - 一个或几个字节的信号处理程序进入该管道(注意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等等。)