了解glibc源代码约定

我一直在寻找一些glibc的源代码,特别是nptl代码,我发现它有点难以理解,因为它似乎有我不熟悉的约定。

例如,我正在查看一个非常小的文件pthread_equal.c ,有一些我有疑问的事情:

22 int 23 __pthread_equal (thread1, thread2) 24 pthread_t thread1; 25 pthread_t thread2; 26 { 27 return thread1 == thread2; 28 } 29 strong_alias (__pthread_equal, pthread_equal) 
  1. 第22和23行的声明看起来像我理解的东西。 它的返回类型为int然后是函数名(thread1, thread2)和参数列表(thread1, thread2) 。 但第24行pthread_t thread1;的声明是什么pthread_t thread1; 和25 pthread_t thread2; 对于? 看起来这些被声明为全局变量,但我不明白其目的。 我在nptl目录中的许多文件中都看到了这种模式,并且无法弄清楚为什么要这样做。

  2. 什么是strong_alias ? 一个快速的谷歌搜索有使用这个的例子,但我没有找到任何文档的链接。

  3. 使用两个下划线__和一些带下划线_某些名称前缀的原因是什么。 我见过的大多数代码使用了两个下划线,但我想我已经看到了一些使用下划线的地方。 例如在pthreadP.h中

     556 /* Old cleanup interfaces, still used in libc.so. */ 557 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, 558 void (*routine) (void *), void *arg); 559 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, 560 int execute); 561 extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, 562 void (*routine) (void *), void *arg); 563 extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, 564 int execute); 

不可否认的是,代码前面带有一个注释,上面写着“旧的清理界面”,但无论哪种方式,我都对这种差异感到好奇,为什么有时会使用一个下划线,有时会使用两个下划线。

有关这些问题的任何信息表示赞赏。

编写该函数时无需符合C89标准的编译器; 它也适用于较旧的编译器。 这是一个非原型函数定义。

 int /* Return type */ function(arg1, arg2) /* Function name and argument names (but no types) */ int arg1; /* Type of arg1 */ char *arg2; /* Type of arg2 */ { /* Body of function */ } 

请注意,参数的定义不必与函数行中的序列相同(我必须将代码从此’K&R’表示法转换为原型表示法,而不是它们出现故障!)。 还要注意以前可以简单地写:

 main(argc, argv) char **argv; { ... } 

argc的隐含类型是int因为它没有被指定为其他任何东西。 glib代码不太可能利用该许可证。 类似地, main()的返回类型是int因为没有给出其他类型。

strong_alias与隐藏和公开共享库中的符号有关。 我没有使用它,所以我不确定所有的后果,但我相信这意味着__pthread_equal()pthread_equal()函数的另一个名称。


__pthread_equal()名称背后的推理的一部分是以C标准为“实现”保留以下划线后跟大写字母或另一个下划线的名称。 根据C标准,诸如’pthread_equal()’之类的名称位于用户的名称空间中。

ISO / IEC 9899:1990(C99标准)说:

7.1.3保留标识符

每个标头声明或定义其关联子条款中列出的所有标识符,并可选地声明或定义其关联的未来库方向子条款和标识符中列出的标识符,这些标识符始终保留用于任何用途或用作文件范围标识符。

– 所有以下划线开头的标识符以及大写字母或另一个下划线始终保留用于任何用途。

– 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。

– 如果包含任何相关标题,则保留以下任何子条款中的每个宏名称(包括未来的库方向)以供指定使用; 除非另有明确说明(见7.1.4)。

– 以下任何子条款中包含外部链接的所有标识符(包括未来的库方向)始终保留用作具有外部链接的标识符。 154)

– 如果包含任何相关标头,则保留下列任何子条款(包括未来库方向)中列出的具有文件范围的每个标识符,以用作宏名称和具有相同名称空间的文件范围的标识符。

没有保留其他标识符。 如果程序在保留它的上下文中声明或定义标识符(除了7.1.4允许的标识符),或者将保留标识符定义为宏名称,则行为是未定义的。

154)具有外部链接的保留标识符列表包括errnomath_errhandlingsetjmpva_end

  1. 旧写作。
  2. 要确保__pthread_equal的类型, pthread_equal要相同。
  3. 区分变量名称,并区分核心区域和用户区域。