为什么说 malloc() 和 printf() 是不可重入的? [英] Why are malloc() and printf() said as non-reentrant?

查看:21
本文介绍了为什么说 malloc() 和 printf() 是不可重入的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 UNIX 系统中,我们知道 malloc() 是一个不可重入的函数(系统调用).这是为什么?

In UNIX systems we know malloc() is a non-reentrant function (system call). Why is that?

同样,printf() 也被称为不可重入;为什么?

Similarly, printf() also is said to be non-reentrant; why?

我知道重入的定义,但我想知道为什么它适用于这些函数.是什么阻止它们保证可重入?

I know the definition of re-entrancy, but I wanted to know why it applies to these functions. What prevents them being guaranteed reentrant?

推荐答案

mallocprintf 通常使用全局结构,并在内部采用基于锁的同步.这就是它们不可重入的原因.

malloc and printf usually use global structures, and employ lock-based synchronization internally. That's why they're not reentrant.

malloc 函数可以是线程安全的,也可以是线程不安全的.两者都不可重入:

The malloc function could either be thread-safe or thread-unsafe. Both are not reentrant:

  1. Malloc 在全局堆上运行,并且同时发生的两个不同的 malloc 调用可能返回相同的内存块.(第二次 malloc 调用应该在获取块的地址之前发生,但块没有标记为不可用).这违反了 malloc 的后置条件,因此该实现不会重入.

  1. Malloc operates on a global heap, and it's possible that two different invocations of malloc that happen at the same time, return the same memory block. (The 2nd malloc call should happen before an address of the chunk is fetched, but the chunk is not marked as unavailable). This violates the postcondition of malloc, so this implementation would not be re-entrant.

为了防止这种影响,malloc 的线程安全实现将使用基于锁的同步.但是,如果从信号处理程序调用malloc,可能会发生以下情况:

To prevent this effect, a thread-safe implementation of malloc would use lock-based synchronization. However, if malloc is called from signal handler, the following situation may happen:

malloc();            //initial call
  lock(memory_lock); //acquire lock inside malloc implementation
signal_handler();    //interrupt and process signal
malloc();            //call malloc() inside signal handler
  lock(memory_lock); //try to acquire lock in malloc implementation
  // DEADLOCK!  We wait for release of memory_lock, but 
  // it won't be released because the original malloc call is interrupted

malloc 被简单地从不同的线程调用时,这种情况不会发生.事实上,可重入概念超越了线程安全性,还要求函数正常工作即使其中一个调用永远不会终止.这基本上就是为什么任何带锁的函数都不会重入的原因.

This situation won't happen when malloc is simply called from different threads. Indeed, the reentrancy concept goes beyond thread-safety and also requires functions to work properly even if one of its invocation never terminates. That's basically the reasoning why any function with locks would be not re-entrant.

printf 函数也对全局数据进行操作.任何输出流通常都使用附加到资源数据的全局缓冲区(用于终端或文件的缓冲区).打印过程通常是将数据复制到缓冲区并随后刷新缓冲区的序列.这个缓冲区应该像 malloc 一样被锁保护.因此,printf 也是不可重入的.

The printf function also operated on global data. Any output stream usually employs a global buffer attached to the resource data are sent to (a buffer for terminal, or for a file). The print process is usually a sequence of copying data to buffer and flushing the buffer afterwards. This buffer should be protected by locks in the same way malloc does. Therefore, printf is also non-reentrant.

这篇关于为什么说 malloc() 和 printf() 是不可重入的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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