当前位置: 首页 > 面试题库 >

如何避免在信号处理程序中使用printf?

柯星辰
2023-03-14
问题内容

由于printf不是可重入的,因此在信号处理程序中使用它并不安全。但是我看过很多使用printf这种方式的示例代码。

所以我的问题是:我们什么时候需要避免printf在信号处理程序中使用,并且有推荐的替代品吗?


问题答案:

您可以使用一些标志变量,在信号处理程序中设置该标志,并printf()在正常操作期间基于main()或程序其他部分中的该标志调用函数。

printf从信号处理程序中调用所有函数(例如)是不安全的。一种有用的技术是使用信号处理程序设置a flag,然后flag
从主程序中检查它并在需要时打印一条消息。

注意,在下面的示例中,信号处理程序ding()alarm_fired在捕获到SIGALRM时将标志设置为1,并alarm_fired检查主函数值以有条件地正确调用printf。

static int alarm_fired = 0;
void ding(int sig) // can be called asynchronously
{
  alarm_fired = 1; // set flag
}
int main()
{
    pid_t pid;
    printf("alarm application starting\n");
    pid = fork();
    switch(pid) {
        case -1:
            /* Failure */
            perror("fork failed");
            exit(1);
        case 0:
            /* child */
            sleep(5);
            kill(getppid(), SIGALRM);
            exit(0);
    }
    /* if we get here we are the parent process */
    printf("waiting for alarm to go off\n");
    (void) signal(SIGALRM, ding);
    pause();
    if (alarm_fired)  // check flag to call printf
      printf("Ding!\n");
    printf("done\n");
    exit(0);
}

参考:Beginning LinuxProgramming,第4版,在本书中,准确说明了您的代码(所需的内容),第11章:进程和信号,第484页

此外,在编写处理程序函数时需要特别小心,因为它们可以异步调用。也就是说,处理程序可能在程序中的任何地方被意外地调用。如果两个信号在很短的间隔内到达,则一个处理程序可以在另一个处理程序中运行。并且,最好声明为volatile sigatomic_t,始终以原子方式访问此类型,以避免不确定中断对变量的访问。(有关详细信息,请阅读:原子数据访问和信号处理)。

阅读定义信号处理程序:了解如何编写可以使用signal()sigaction()函数建立的信号处理程序功能。手册页
中授权功能的列表,在信号处理程序中调用此功能是安全的。



 类似资料:
  • 问题内容: 我需要在接收到任何终止命令(如SIGTERM和SIGKILL)时写入日志文件。 我可以注册SIGTERM,但是如何处理SIGKILL信号? 问题答案: 您不能,至少不是因为进程被杀死。 您 可以 做的是安排父进程监视子进程的死亡,并采取相应的措施。任何体面的过程监控系统(例如daemontools)都内置了这样的工具。

  • 我正在开发一个用PHP编写的预分叉TCP套接字服务器。 守护进程(父进程)分叉一定数量的子进程,然后等待,直到它被告知退出并且子进程都走了或者它收到信号。 SIGINT和SIGTERM使其将SIGTERM发送给所有子级。 孩子们建立了他们自己的信号处理器:SIGTERM导致一个干净的退出。SIGUSR1导致它转储一些状态信息(只需在下面的示例代码中打印出它收到了信号)。 如果子异常退出,则父级启动

  • 本文向大家介绍Spark处理数据排序问题如何避免OOM,包括了Spark处理数据排序问题如何避免OOM的使用技巧和注意事项,需要的朋友参考一下 错误思想 举个列子,当我们想要比较 一个 类型为 RDD[(Long, (String, Int))] 的RDD,让它先按Long分组,然后按int的值进行倒序排序,最容易想到的思维就是先分组,然后把Iterable 转换为 list,然后sortby,但

  • 问题内容: 我想编写一个信号处理程序来捕捉SIGSEGV。我保护一块内存以供使用 这样可以保护从缓冲区开始的内存的页面大小字节免受任何读取或写入的影响。 其次,我尝试读取内存: 这将生成一个SIGSEGV,并且将调用我的处理程序。到目前为止,一切都很好。我的问题是,调用处理程序后,我想通过以下方式更改内存的访问写入: 并继续正常运行我的代码。我不想退出该功能。在将来对同一内存进行写操作时,我想再次

  • 我听说过很多关于在Excel VBA中使用的憎恶是可以理解的,但我不确定如何避免使用它。我发现,如果我能够使用变量而不是函数,那么我的代码将更加可重用。但是,如果不使用,我不确定如何引用东西(如等)。 我已经找到了这篇关于范围的文章和这个关于不使用select的好处的例子,但是我找不到任何关于如何使用的东西。

  • 问题内容: 我想自己开发一个探查器,我想解释一下我所看到的。即使在最简单的程序中,也总是会出现一些默认线程: 销毁JavaVM 信号调度器 终结器 参考处理程序 尽管他们的名字很能说明问题,但我想获得更多信息。似乎这些线程没有记录在案,是否有人知道挖掘这些信息的来源,甚至确切地知道这些线程的作用? 问题答案: DestroyJavaVM是一个线程,该线程在程序退出时卸载Java VM。在大多数情况