【问题标题】:Why is _GNU_SOURCE macro required for pthread_mutexattr_settype() while it is in POSIX/IEEE standard?为什么在 POSIX/IEEE 标准中 pthread_mutexattr_settype() 需要 _GNU_SOURCE 宏?
【发布时间】:2013-08-24 21:26:36
【问题描述】:

我用 C 语言编写了一个多线程服务器程序,它回显了客户端发送的所有数据。

最初,我在程序中使用poll() 函数来检测POLLRDHUP 事件,为此我定义了_GNU_SOURCE 宏(此事件定义为here)。

后来我更新了我的代码并删除了poll() 函数,但是我忘了删除_GNU_SOURCE 宏。

现在我的代码终于完成了(发布时间有点长,超过 250 行)。在删除宏之前,我正在使用以下方法编译我的程序:

gcc multi_thread_socket_v4.c -Wall -Werror -g -lpthread -o multi_thread_socket

它运行良好:没有错误,没有警告

在我删除宏定义,并使用相同的命令行编译后,gcc 的输出是:

multi_thread_socket_v4.c: In function ‘main’:
multi_thread_socket_v4.c:194: warning: implicit declaration of function ‘pthread_mutexattr_settype’
multi_thread_socket_v4.c:194: error: ‘PTHREAD_MUTEX_ERRORCHECK’ undeclared (first use in this function)
multi_thread_socket_v4.c:194: error: (Each undeclared identifier is reported only once
multi_thread_socket_v4.c:194: error: for each function it appears in.)

我已经包含了所有必需的库,因为它最初运行良好。

我在/usr/include/pthread.h 偷看了pthread.h 并发现了这一点:

/* Mutex types.  */
enum
{
  PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
  ,
  PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
  PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
  PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
  PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
  /* For compatibility.  */
  , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};

还有这个:

#ifdef __USE_UNIX98
/* Return in *KIND the mutex kind attribute in *ATTR.  */
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
                      __attr, int *__restrict __kind)
     __THROW __nonnull ((1, 2));

/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
   PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
   PTHREAD_MUTEX_DEFAULT).  */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
     __THROW __nonnull ((1));

checked out here 检查__USE_UNIX98 是否是功能测试宏,但它不存在。

所以请帮助我了解错误的原因,因为gcc 的函数和宏显示错误are defined in POSIX standard。我不知道需要更多关于我的问题的信息,所以请告诉我,我会更新我的问题。

【问题讨论】:

  • 最明显的答案是该功能不在 Posix 中,而仅在 Linux 中。默认情况下,pthread 库尝试符合 Posix。
  • 另请注意,双下划线宏不适合您使用;它们在内部重置。您只能使用 _GNU_SOURCE_BSD_SOURCE 等顶级宏来控制库的哪些部分被拉入。
  • @KerrekSB : 但是函数pthread_setattr_settype() 和宏PTHREAD_MUTEX_ERRORCHECKPOSIX standard,那么为什么需要定义_GNU_SOURCE
  • 但它们不是标准的 C,所以它们需要定义 something ...不一定是 _GNU_SOURCE,它是一个厨房水槽定义,会拖入很多东西。

标签: c multithreading gcc client-server language-features


【解决方案1】:

你应该使用

#define _POSIX_C_SOURCE 200112L

如果您想使用诸如 pthread_mutexattr_settype 之类的 POSIX 功能...请参阅http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html

另一种可能是

#define _XOPEN_SOURCE 700

http://man7.org/linux/man-pages/man7/feature_test_macros.7.htmlhttp://pubs.opengroup.org/onlinepubs/9699919799/

设置 _GNU_SOURCE 包括 POSIX 和许多其他定义。

附:我希望包括 <pthread.h> 包括 <features.h>,默认情况下将 _POSIX_C_SOURCE 定义为 200112L,但您可能已经定义了一些覆盖它的东西......有关详细信息,请参阅系统上的 /usr/include/features.h符号及其用法。

【讨论】:

  • 明白你的意思,将阅读它们。顺便说一句,this link I found 是最新的标准修订版。
  • @nishant 该链接在我提供的链接中。我真的不认为你需要阅读它们,你只需要提供定义。我在这里做的是回答你的问题。
  • 谢谢,尽管_XOPEN_SOURCE 700 成功了(_GNU_SOURCE 也是如此)。但它不会影响其他功能吗?我的意思是其他功能可能开始表现不同。
  • @nishant 大多数情况下,它会影响可见的符号,而不是行为。如果您明确要求使用较旧的过时版本的标准,您可能会改变行为。
【解决方案2】:

没有,你的问题可能出在其他地方。

我刚刚编译了一个小程序,内容如下:

#include <pthread.h>

int main(int argc, char **argv)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

    return 0;
}

这与 gcc -pthread -Wall -Werror a.c 完美编译。

您的程序的另一部分可能会导致这种情况,例如。做一些愚蠢的事情,比如定义_PTHREAD_H,或者其他一些小的破坏。

您可能想尝试使用deltacreduce 之类的工具来获得最小的测试用例,这可能会使问题变得明显。

【讨论】:

  • 您的代码在我的机器上给出了同样的错误。机器规格:操作系统:SLES 10 SP3 x86-64。
  • @nishant 这里还有其他答案。试试我的。
  • @nishant:这很奇怪。我已经在 vanilla debian 安装上构建了它。 AFAIK,您不必显式定义任何功能宏,因为pthread.h 中包含的features.h 应该定义这些,如果没有定义其他内容(这就是为什么在这里编译,我刚刚使用gcc -E -fdirectives-only 进行了检查。)
  • 我还要注意,设置一些东西会破坏这一点,例如。定义__STRICT_ANSI__ (通过-ansi 标志),或_POSIX_SOURCE_POSIX_C_SOURCE。 (在我的情况下,这最终设置了启用该功能的__USE_XOPEN2K8
  • 我研究了gcc file.c -E -fdirectives-only 的输出,但在那里没有定义__USE_UNIX98。但是在#define _XOPEN_SOURCE 700 之后,这条线#define __USE_UNIX98 出现在最后。
【解决方案3】:

当您使用 库(例如 2.1.x)时,您应该使用

#define __USE_UNIX98

使用以“__”开头的宏通常不是一个好主意,但有时这是唯一的方法……另请参阅this discussion

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    相关资源
    最近更新 更多