【问题标题】:Understanding glibc source code conventions了解 glibc 源代码约定
【发布时间】:2012-03-14 02:38:24
【问题描述】:

我一直在查看 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);
    

诚然,代码前面有一条注释,上面写着“旧的清理接口”,但无论哪种方式,我都很好奇其中的区别以及为什么有时使用一个下划线,有时使用两个下划线。

感谢您提供有关这些问题的任何信息。

【问题讨论】:

    标签: c pthreads libc


    【解决方案1】:

    函数的编写不需要符合 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) 具有外部链接的保留标识符列表包括errno、math_errhandling、 setjmp 和 va_end。

    【讨论】:

      【解决方案2】:
      1. 旧文。
      2. 保证__pthread_equal、pthread_equal的类型相同。
      3. 区分变量名,区分核心区和用户区。

      【讨论】:

        猜你喜欢
        • 2012-09-22
        • 1970-01-01
        • 2011-09-15
        • 1970-01-01
        • 2011-01-27
        • 2012-12-17
        • 2017-10-08
        • 2013-11-20
        相关资源
        最近更新 更多