为什么 printf 不是 asyc 信号安全函数?

为什么 printf 不是 asyc 信号安全函数?

我们知道这printf不是异步信号安全函数。以下是我的基本理解:

假设我们已经调用了printfinmain方法,因此内容被写入 stdio 缓冲区,就在缓冲区刷新到文件之前,信号到达并且信号处理程序也调用printf,第二个printf将其内容追加到缓冲区,现在是缓冲区第一次调用和第二次调用的内容不一致,这是不正确的,因此我们不能在信号处理程序中使用非异步安全函数。我的理解正确吗?

如果我的理解是正确的,那么异步安全函数如何解决这个问题呢?因为安全函数仍然需要处理缓冲区,其中仍然可能包含宝贵的调用的缓冲区数据?

答案1

printf是非异步信号安全的,因为正如您所描述的,它最终会在没有同步的情况下操纵全局状态。为了增加乐趣,它不一定是可重入的。在您的示例中,信号可能会在第一个printf运行时处理,而第二个信号printf可能会扰乱第一个调用的状态。

推荐的异步信号安全方法是让信号处理程序在某处设置一个标志,并让主程序流处理该标志。这可以避免重新进入、序列化输出的问题,并有助于保持信号处理程序的速度。

答案2

我的理解正确吗?

大多。还有一个问题是,在调整缓冲区的偏移量和大小时,嵌套的 printf 调用会互相踩踏,这不仅会导致数据不一致,还会导致崩溃。

异步安全函数如何解决这个问题?

有两种异步信号安全函数:

  • 像 strlen(3) 这样的可重入函数,除了用于保存局部变量、参数和返回值的内存之外,不会修改任何内存。

  • 函数是简单的系统调用包装器,如kill(2)、waitpid(2)等:它们的用户态部分是完全可重入的,如上所述,而对于内核部分,内核会处理一切。

相关内容