如何避免在信号处理用printf? [英] How to avoid using printf in a signal handler?

查看:139
本文介绍了如何避免在信号处理用printf?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于的printf 是不可重入的,它不应该是安全的信号处理程序来使用它。但我见过很多使用例如codeS的的printf 这样的。

Since printf is not reentrant, it's not supposed to be safe to use it in a signal handler. But I've seen lots of example codes that uses printf this way.

所以我的问题是:什么时候我们需要避免在信号处理程序使用的printf ,并且是有建议的替换

So my question is: when do we need to avoid using printf in a signal handler, and is there a recommended replacement?

推荐答案

您可以使用一些标志变量,设置信号处理程序内该标志,并基于该旗呼的printf()在正常操作期间的程序的主()或其它部分的功能​​。

You can use some flag variable, set that flag inside signal handler, and based on that flag call printf() function in main() or other part of program during normal operation.

这不是安全地调用所有功能,如的printf ,从信号处理程序中。
     一个有用的技术是使用信号处理程序来设置标志然后检查标志
     从主程序,如果需要打印的消息。

It is not safe to call all functions, such as printf, from within a signal handler. A useful technique is to use a signal handler to set a flag and then check that flag from the main program and print a message if required.

例如,在公告的下方,信号处理程序丁()设置一个标志 alarm_fired 1为SIGALRM抓住并主要功能 alarm_fired 价值进行检查,有条件正确调用printf。

Notice in example below, signal handler ding() set a flag alarm_fired to 1 as SIGALRM caught and in main function alarm_fired value is examined to conditionally call printf correctly.

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);
}

<子>参考:开始Linux的编程,第四版,在这本书中正是您的code解释(你想要的),第11章:进程和信号,484页

Reference: Beginning Linux Programming, 4th Edition, In this book exactly your code is explained (what you want), Chapter 11: Processes and Signals, page 484

此外,需要特别照顾的书面处理函数,因为它们可以异步调用。即,一个处理程序可能在程序中,取消predictably任何点被调用。如果在很短的时间间隔内两个信号到达,一个处理程序可以在另一运行。而它被认为是更好的做法,声明挥发性sigatomic_t ,这种类型总是原子访问,避免对中断给一个变量的访问不确定性。 (阅读:原子数据访问和信号处理的详细赎罪)。

Additionally, you need to take special care in writing handler functions because they can be called asynchronously. That is, a handler might be called at any point in the program, unpredictably. If two signals arrive during a very short interval, one handler can run within another. And It is considered better practice to declare volatile sigatomic_t, this type are always accessed atomically, avoid uncertainty about interrupting access to a variable. (read: Atomic Data Access and Signal Handling for detail expiation).

信号处理函数:学习如何编写可与信号建立一个信号处理函数()的sigaction()功能。

手册页面,呼叫信号处理器中,此功能是安全的。

Read Defining Signal Handlers :to learn how to write a signal handler function that can be established with the signal() or sigaction() functions.
List of authorized functions in manual page, calling this function inside signal handler is safe.

这篇关于如何避免在信号处理用printf?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆