阅读glibc源码

摘要:
All-fit gnugcc_attribute__机制是相关的。gcc文档中有一章介绍了Attributesyntax,其中解释了attribute__机制。参考链接如下:1__ attribute__((别名)):
GNU C - Using GNU GCC __attribute__ mechanism 01
 

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

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

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

阅读glibc源码第1张

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

阅读glibc源码第2张

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

阅读glibc源码第3张

 现在只是知道,在链接的时候,寻找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宏的实现:

阅读glibc源码第4张

 最后一句中 __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:

阅读glibc源码第5张

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

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

 

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

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

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

阅读glibc源码第6张

 

 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*/
}

输出结果如下:

阅读glibc源码第7张

 

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

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

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

glibc中有大量的实例:

阅读glibc源码第8张

 

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

 

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

 扫平一切障碍~

 

  

        

      

 
分类: C

免责声明:文章转载自《阅读glibc源码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇UIScrollView浏览一组图片,且图片与图片之间有间隔cookie一些问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

BTC_ETH_USDT_自动充提币API接口,钱包对接交易所教程!

 以目前市面上用的最多的优盾钱包开放平台为例。 详细的接口文档如下: 官方接口文档链接:https://www.uduncloud.com/gateway-interface 1、目录 1.1、生成地址 1.2、提币 1.3、代付 1.4、交易回调 1.5、校验地址合法性 1.6、获取商户支持币种信息 2、接口明细 1、生成地址 1.1 场景说明 请求指...

获取JS数组中的相同元素的名称和数量

Js代码   <script>   var ary =["aaa","露露","bbb","aaa","ccc","ccc","aaa","露露","haha"];   var res = [];   ary.sort();   for(var i = 0;i<ary.length;)   {        var count = ...

iis无法启动, 找出占用80端口的罪魁祸首

有时候大家会碰到 "iis 无法启动,发生意外错误0x8ffe2740" 的错误 ,其实这个一般是其他进程占用了80端口导致 iis 启动失败, helix oracle skype wms 都有可能占用 iis 的80端口. 有时候防火墙规则也会对iis产生影响 http://hi.baidu.com/yygyd/blog/item/78d59212b2...

机器学习笔记14-----SVM实践和分类器的性能的评价指标(了解python画图的技巧)

1.主要内容 2.SVM的应用 (1)利用SVM处理分类问题 分类器的性能的评价指标: 应用案例: accuracy=3/6=0.5 precision=3/5=0.6 recall=3/4=0.75 3.代码示例 (1)鸢尾花SVM案例 #!/usr/bin/python # -*- coding:utf-8 -*- import nump...

hsql整理

一、行转列的使用1、问题hive如何将a       b       1a       b       2a       b       3c       d       4c       d       5c       d       6变为:a       b       1,2,3c       d       4,5,6 2、数据test.txt...

c语言_头文件_windows.h

概述 Win32程序的开头都可看到: #include <windows.h> WINDOWS.H是一个最重要的头文件,它包含了其他Windows头文件,这些头文件的某些也包含了其他头文件。这些头文件中最重要的和最基本的是: WINDEF.H 基本数据类型定义。 WINNT.H 支持Unicode的类型定义。 WINBASE.H Kernel(...