6

我正在将 getaddrinfo 用于与 IPv6 相关的 C 项目。我电脑上的“man getaddrinfo”(uname -a: 3.5.0-23)只表示它是“可重入的”。所以我猜它不是线程安全的。

在需要线程安全的场景下,如何处理?我还检查了 UNP,但似乎没有提供具体答案。非常感谢。

4

4 回答 4

13

getaddrinfo()确实是线程安全的。这是RFC 3493 第 6.1 节要求的:

函数 getaddrinfo() 和 freeaddrinfo() 必须是线程安全的。

在某些平台上,gethostbyname()它是线程安全的,但在其他平台上则不是。gethostbyname()不在所有平台上的都是可重入的。如果您在同一个线程中调用gethostbyname()然后gethostbyname()再次调用,则第一次调用的数据将被第二次调用的数据覆盖。这是因为gethostbyname()通常在内部使用静态缓冲区,这就是为什么您必须在再次调用之前复制数据gethostbyname()getaddrinfo()不会遇到这个问题,因为它addrinfo每次调用时都会分配一个新结构。

于 2013-09-04T01:00:57.860 回答
4

好吧,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()  │               │                    │
   └────────────────┴───────────────┴────────────────────┘

注意 env 和 locale 属性:

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

于 2018-10-05T15:01:21.997 回答
0

getaddrinfo() 是线程安全的。所有(或几乎所有)函数手册页都有关于线程安全的信息。Reentrant表示线程安全。

于 2019-04-25T22:00:36.880 回答
0

getaddrinfo()是 POSIX 标准的一部分,POSIX 标准要求:

freeaddrinfo() 和 getaddrinfo() 函数应该是线程安全的。

来源: http: //pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html

如果不是这种情况,操作系统可能不会声称符合 POSIX。

您可能听说过的符合 POSIX 的正式操作系统:
AIX、BSD、IRIX、macOS、(Open)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

于 2019-03-29T17:16:16.053 回答