我正在使用getaddrinfo来处理与IPv6相关的C项目。 " man getaddrinfo"在我的电脑上(uname -a:3.5.0-23)只表示它是"可重入"。所以我猜它不是线程安全的。
在需要线程安全的情况下,如何处理它?我也检查了UNP,但似乎没有提供具体的答案。非常感谢。
答案 0 :(得分:11)
getaddrinfo()
确实是线程安全的。这是RFC 3493 Section 6.1:
函数getaddrinfo()和freeaddrinfo()必须是线程安全的。
在某些平台上,gethostbyname()
是线程安全的,但在其他平台上却不是。 gethostbyname()
并非在所有平台上都是可重入的。如果您呼叫gethostbyname()
然后再次在同一个线程中呼叫gethostbyname()
,则第一次呼叫的数据将被第二次呼叫中的数据覆盖。这是因为gethostbyname()
通常在内部使用静态缓冲区,这就是为什么在再次调用gethostbyname()
之前必须复制数据的原因。 getaddrinfo()
不会遇到这个问题,因为每次调用它时都会分配一个新的addrinfo
结构。
答案 1 :(得分:1)
好吧,getaddrinfo在某些平台上不是线程安全的,例如Linux:http://man7.org/linux/man-pages/man3/getaddrinfo.3.html
┌────────────────┬───────────────┬────────────────────┐
│Interface │ Attribute │ Value │
├────────────────┼───────────────┼────────────────────┤
│getaddrinfo() │ Thread safety │ MT-Safe env locale │
├────────────────┼───────────────┼────────────────────┤
│freeaddrinfo(), │ Thread safety │ MT-Safe │
│gai_strerror() │ │ │
└────────────────┴───────────────┴────────────────────┘
注意环境和语言环境:
Other safety remarks
Additional keywords may be attached to functions, indicating features
that do not make a function unsafe to call, but that may need to be
taken into account in certain classes of programs:
locale Functions annotated with locale as an MT-Safety issue read
from the locale object without any form of synchronization.
Functions annotated with locale called concurrently with
locale changes may behave in ways that do not correspond to
any of the locales active during their execution, but an
unpredictable mix thereof.
We do not mark these functions as MT-Unsafe, however, because
functions that modify the locale object are marked with
const:locale and regarded as unsafe. Being unsafe, the latter
are not to be called when multiple threads are running or
asynchronous signals are enabled, and so the locale can be
considered effectively constant in these contexts, which makes
the former safe.
env Functions marked with env as an MT-Safety issue access the
environment with getenv(3) or similar, without any guards to
ensure safety in the presence of concurrent modifications.
We do not mark these functions as MT-Unsafe, however, because
functions that modify the environment are all marked with
const:env and regarded as unsafe. Being unsafe, the latter
are not to be called when multiple threads are running or
asynchronous signals are enabled, and so the environment can
be considered effectively constant in these contexts, which
makes the former safe.
因此,如果不考虑它,您将得到随机的段错误。有关详细信息,请参见这个旧的glibc错误讨论:https://sourceware.org/bugzilla/show_bug.cgi?id=13271
答案 2 :(得分:0)
getaddrinfo()
是POSIX标准的一部分,POSIX标准要求:
freeaddrinfo()和getaddrinfo()函数应是线程安全的。
来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html
如果不是这样,则操作系统可能不会声称自己符合POSIX。
您可能听说过的操作系统正式符合POSIX:
AIX,BSD,IRIX,macOS,(开放式)Solaris,QNX以及其他几个产品。
在这些平台上,您可以依靠getaddrinfo()
是线程安全的。
众所周知的操作系统未正式符合POSIX,但为了获得软件兼容性,始终试图尽可能接近POSIX标准:
BeOS,FreeBSD,GNU,iOS,Linux,NetBSD,OpenBSD以及其他几种。
在这些平台上,您不能依赖getaddrinfo()
完全是线程安全的,但是您可以肯定它是足够线程安全的,因此您可以在应用程序中的多个线程中使用它,而不必对其进行任何锁定。
请注意,getaddrinfo()
在Linux上也是线程安全的,因为只有当您的代码在运行多个线程时更改了语言环境或环境时,它才会变为线程不安全的,并且这样做被认为对其线程不安全。拥有。因此,如果您执行了无论如何都被禁止的操作,则只能使getaddrinfo()
处于线程不安全状态(嗯,这并不是真正被禁止的操作,但这样做后果自负,因为这样做不安全)。
还要注意,即使手册页中没有提到(某些POSIX手册页没有提到线程安全性),POSIX标准实际上也规定了:
3.407线程安全
可以与其他线程并发安全地调用线程安全函数 调用相同的函数,或调用任何其他线程安全的 功能,由多个线程组成。 系统中定义的每个功能 除非明确声明,否则POSIX.1-2017的接口量是线程安全的 例子是任何“纯”函数,即 在访问静态存储或对象时将其锁定为互斥 在线程之间共享。
来源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
答案 3 :(得分:0)
getaddrinfo()是线程安全的。所有(或几乎所有)功能手册页都有有关线程安全的信息。 Reentrant
表示线程安全。