在 UNIX 系统中我们知道malloc()
是不可重入函数(系统调用)。这是为什么?
相似地,printf()
也被认为是不可重入的;为什么?
我知道可重入的定义,但我想知道为什么它适用于这些函数。
是什么阻止了它们保证可重入?
malloc
and printf
通常使用全局结构,并在内部采用基于锁的同步。这就是为什么它们不可重入。
The malloc
函数可以是线程安全的,也可以是线程不安全的。两者都是不可重入的:
Malloc 在全局堆上运行,并且有可能两次不同的调用malloc
同时发生,返回相同的内存块。 (第二次 malloc 调用应该在获取块的地址之前发生,但该块未标记为不可用)。这违反了后置条件malloc
,所以这个实现不会是可重入的。
-
为了防止这种影响,线程安全的实现malloc
将使用基于锁的同步。但是,如果从信号处理程序调用 malloc,则可能会发生以下情况:
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
只是从不同的线程调用。事实上,可重入的概念超出了线程安全的范围,还需要函数才能正常工作即使它的调用之一永远不会终止。这基本上就是为什么任何带锁的函数都不可重入的原因。
The printf
函数也对全局数据进行操作。任何输出流通常都会使用附加到要发送到的资源数据的全局缓冲区(用于终端或文件的缓冲区)。打印过程通常是将数据复制到缓冲区并随后刷新缓冲区的序列。该缓冲区应该以同样的方式受到锁的保护malloc
做。所以,printf
也是不可重入的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)