理解glibc源代码规范

11

我一直在查看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的函数名__pthread_equal和参数列表(thread1,thread2)。但是,第24行的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);
承认该代码有一个注释,称为“旧清理接口”,但无论如何,我很好奇它们之间的区别以及为什么有时会使用一个下划线,有时会使用两个下划线。 任何有关这些问题的信息都将不胜感激。
2个回答

12

这个函数的编写不需要符合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 标准中以下划线后跟大写字母或另一个下划线开头的名称“保留给实现”。诸如“pthread_equal()”之类的名称根据 C 标准属于用户命名空间。

ISO/IEC 9899:1990(C99 标准)中写道:

  

7.1.3 保留标识符

     

每个标头声明或定义其关联子条款中列出的所有标识符,并且   可以选择声明或定义其关联的将来库方向中列出的标识符   子句和始终保留为任何用途或用于文件的标识符   作用域标识符。

     

—所有以下划线和大写字母或另一个下划线开头的标识符都保留给任何用途。

     

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

     

—以下任何子句中的每个宏名称(包括将来的库)   方向)根据其关联的头文件中包含的规定保留用途;   除非明确说明否则(参见 7.1.4)。

     

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

     

—在以下任何子句中列出的具有文件作用域的每个标识符   (包括将来的库方向)如果包含了任何关联的头文件,则保留用于   作为宏名称和在同一名称空间中具有文件作用域的标识符。

     

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

     

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


2
  1. 旧的写法。
  2. 为了确保__pthread_equalpthread_equal类型相同。
  3. 区分变量名称,并区分核心区域和用户区域。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接