我需要为Sendmail开发一个milter,并且考虑了很长一段时间我应该使用哪种语言/框架。最后,我决定用普通C语言直接使用milter。
我学习过milter API文档,认为我已经掌握了这些概念。但有一件事让我很担心。来自本节
单个筛选进程可以同时处理任意数量的连接。因此,所有过滤回调必须是可重入的,并使用一些适当的外部同步方法来访问全局数据.
虽然我非常理解为什么回调必须是线程安全的,但我不能理解为什么它们必须是重新进入的。我无法想象可以从中断或信号处理程序中调用这些回调(可能除了中止回调之外,我将不得不重新读取该回调)。
要求重新进入的问题是,可重入函数不能调用不可重入的代码。因此,如果回调必须是可重入的,那么我就不能在其中使用malloc()
和大多数其他库函数;来自man 3 malloc
。
为了避免多线程应用程序中的损坏,内部使用互斥来保护这些函数所使用的内存管理数据结构。
这无疑意味着malloc()
是线程安全的,而且可能意味着malloc()
不是可重入者,因此没有使用它的函数。
所以我有两个问题:
1) milter回调是否真的需要重新进入,或者这实际上是milter文档中“需要线程安全”的非常奇怪的措辞吗?
2)如果他们真的需要重新进入,我怎样才能回避上述问题?由于milter的特性,我很难想象在不使用malloc()
和其他不可重入库函数的情况下,如何在回调中做一些合理的事情。
发布于 2021-06-27 07:41:52
在Milter-API的上下文中(它还强调它在内部使用posix线程),“可重入”函数被定义为可以安全地同时从多个线程执行的函数。这意味着不产生种族条件。
这个术语的使用与其他UNIX/Linux文档(如strtok
)是一致的。
strtok_r()
函数是strtok()
的可重入版本。。。 ┌───────────┬───────────────┬───────────────────────┐│接口│属性│值││不安全竞赛:strtok├───────────┼───────────────┼───────────────────────┤│strtok_r()│线程安全│MT-安全│└───────────┴───────────────┴───────────────────────┘
还请参阅其他*_r()
函数,如ctime_r()
、gmtime_r()
等。
https://stackoverflow.com/questions/47053441
复制相似问题