zoukankan      html  css  js  c++  java
  • 阅读glibc源码

    GNU C - Using GNU GCC __attribute__ mechanism 01

     

    近来阅读glibc源码的时候遇到很多关于__attribute__的问题,索性就查找了相关的资料,学习了一下.

    要是不解决了这个问题,有的时候还真的是比较难下手.就拿glibc来说,使用xcscope搜索POSIX pthread

    函数: pthread_create,得到的结果如下:

    如果一路跟进函数的话,最后会发现这样子的一个宏定义:

    下面是GNU glibc开发人员对此类宏的注释,看起来直白一点:

     现在只是知道,在链接的时候,寻找pthread_create会被链接到__pthread_create_2.1/__pthread_create_2.0.


    上面展现的是GNU glibc中很常用的编程技巧,这不是本文的重点,关于这点,我也没有深究.如果,有了解的同学可以给我留信息哈.希望多多指教.

     

    下面来说说另外一种,glibc中很多地方都使用别名机制,都合 gnu gcc的 __attribute__ mechanism有关系.在gcc的文档中有关于 Attribute syntax 的章节,

    其中就讲解了_attribute__ mechanism. 参考链接如下:

                 Attribute Syntax: http://gcc.gno.org/onlinedoc/gcc-4.7.1/gcc/Attribute-Syntax.html#Attribute-Syntax

     

    Attribute Syntax分为三个部分:

        Function Attribute:  函数attribute语义

                  Variable  Attribute:   变量attribute语义

          Type       Attribute:   类型attribute语义

     

     

    下面就各选取第一部分中一些内容,解释一下:

    一、Function Attribute:

    1.__attribute__((alias)):  为一个symbol声明一个别名

    return-type newname([arguments-list]) __attribute__((alias("oldname")))

     oldname:  原始函数名

     newname:   原始函数的别名

     来看看glibc中 _strong_alias宏的实现:

     最后一句中 __typeof(name) 就是原始函数的返回类型, aliasname是别名, 后面的就不需要解释了吧...

     下面看一段小程序吧:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>
    #include <stdlib.h>
     
    void foo()
    {
        printf("\nInside %s\n",__FUNCTION__);
    }
     
    void _foo() __attribute__((alias("foo")));
     
    //@Author : forest
    int main(int args,char ** argv)
    {
        _foo();
        return EXIT_SUCCESS;
    }

     输出很简单,就是通过别名调用了原始函数.

    2.__attribute__((const)): const这个attribute是在gcc2.5以后添加的,以前的旧版本是没有的.const attribute只能用于带有数值参数类型的函数上.

               因为带有数值参数的函数返回值是相同的,所以在多次调用的时候,编译器进行优化,只需要执行一次就可以得到执行的结果.

                  const attribute是让编译器进行优化.

    1
    2
    3
    4
    5
    6
    7
    8
    int Function_Attribute_const_0(int b) __attribute__((const));
    int Function_Attribute_const_0(int b)
    {
          int aLocal = 0;
          aLocal += Function_Attribute_const_0(b);
          aLocal += Function_Attribute_const_0(b);
          return aLocal;
    }

     其中的"Function_Attribute_const_0(int)"函数将会执行一次.

     


    3.__attribute__((constructor|destructor(PRIORITY))): 这个在上篇博文中已经说过了:
    GNU C - 一个别致的HelloWorld程序 引申到: __attribute__((constructor)|(destructor)(PRIORITY))

     

    4.__attribute__((deprecated)): deprecated,弃用. 如果在源文件在任何地方地方使用deprecated attribute函数,编译器将会发出警告.

       __attribute__((deprecated(MSG))): MSG,将在编译器warnning中输出.

    下面改写一下前面的小例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>
    #include <stdlib.h>
     
    __attribute__((deprecated("foo函数已经被弃用"))) void foo()
    {
        printf("\nInside %s\n",__FUNCTION__);
    }
     
    void _foo() __attribute__((alias("foo")));
     
    //@Author : forest
    int main(int args,char ** argv)
    {
        _foo();
     
        foo();
        return EXIT_SUCCESS;
    }

     Output:

    可以看出在上面的例子中,声明foo()被弃用,在main()中被调用在编译的时候会抛出warnning.但是使用别名调用就不会输出

    warnning.官网的资料中关于这点没有相关介绍,以实践为准吧.

     

    5.__attribute__(format(archetype,string-index,first-to-check)): format attribute提供了对printf, scanf, strftime, strfmon类型函数

    的参数和对应format类型的检查.(这英文翻译起来有点别扭,将就一下吧~)

    glibc中有很多关于format attribute的使用:

     

     archtype: 决定format string将会被怎样解释.解释的类型应该是printf, scanf, strftime, gnu_printf, gnu_scanf, gnu_strftime..(也可以像glibc一样使用__printf__,

    __scanf__,__strftime ...以下划线开始和结尾).


    string-index: 函数的参数从左到右以此序号为1,2,3递增.string-index就是fmt的序号.

     

    first-to-check: 参数列表中第一个和fmt形式比较的参数.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
    #include <stdlib.h>
     
    void foo(const char *fmt,...) \
        __attribute__((__format__(__printf__,1,2)));
     
    //@Author : forest
    int main(int args,char ** argv)
    {
        //@test
        foo("\n%d %d","test_a","test_b");  
     
        return EXIT_SUCCESS;
    }
     
    void foo(const char *fmt,...)
    {
        /*do nothing*/
    }

    输出结果如下:

     

    6.__attribute__((weak)): weak symbol,弱符号. 若存在两个相同的全局符号时,会引发重定义错误. 如果使用weak attribute,则当

                                           weak symbol和non-weak symbol同时存在的时候,linker会使用non-weak symbol.若只有weak symbol

                  存在的时候则只使用weak symbol.

    glibc中有大量的实例:

     

    补充: __attribute__ 后面的属性字段也是可以连在一起用的。

     

     到这里,第一部分就算完了。如果粗略看了一下这些,阅读一些源码库基本上就不会出现找不到函数实现的问题了.

     扫平一切障碍~

     

      

            

          

     
    分类: C
  • 相关阅读:
    JS防抖和节流
    移动端屏幕适配
    vue、react对比
    HTTP缓存
    程序员必备技术网站
    W3C标准、表现与数据分离、web语义化
    VUE的响应式原理
    react更新渲染及渲染原理
    ubuntu下mysql的环境搭建及使用
    apktool反编译工具
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2582721.html
Copyright © 2011-2022 走看看