Chinaunix首页 | 论坛 | 博客
  • 博客访问: 84118
  • 博文数量: 27
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-21 14:41
文章分类
文章存档

2014年(1)

2013年(20)

2012年(6)

我的朋友

分类: LINUX

2013-05-14 18:05:03

原文地址:关于__init的问题 作者:isuxue

#define __init          __attribute__ ((__section__ (".init.text")))
以__init修饰的函数并非程序中显式调用的,而是被放到特定的(代码、数据)段中,在初始化的时候调用。

相关的内容有(供你参考):代码是linux-2.6.35.4的

内核初始化宏
#define __define_initcall(level,fn,id) \
    static initcall_t __initcall_##fn##id __used \
    __attribute__((__section__(".initcall" level ".init"))) = fn
 
1.    宏定义中的## 连接符与# 符
## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元。
#符是把传递过来的参数当成字符串进行替代。
 
#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;
paster( 9 );
编译时,pster(9)被扩展为:
printf( "token" "9" " = %d", token9 );
屏幕显示:int token9 = 9;
 
2.    initcall_t 函数指针类型
typedef int (*initcall_t)(void);
 
3.    gcc attribute机制
__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
  __attribute__书写特征是:__attribute__前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数。
  __attribute__语法格式为:
  __attribute__ ((attribute-list))
  其位置约束为:
  放于声明的尾部“;”之前。
 
__attribute__ 中的 section 属性对代码段起作用,其格式为
__attribute__ ((section("section_name")))
其意是将作用的函数或数据放入指定名为 "section_name" 输入段中
 
输入段和输出段是相对于要生成最终的 elf 或 binary 时的 link 过程来说的。link 过程的输入大都是由源代码编译生成的目标文件.o ,那么这些 .o 文件中包含的段相对 link 过程来说就是输入段,而 link 的输出一般是可执行文件 elf 或库等,这些输出文件中也包含段,这些输出文件中的段叫做输出段。输入段和输出段没有必然联系,为互相独立,只是在 link 过程中,link 程序会根据一定的规则 (这些规则来源于 link script),将不同的输入段组合到不同的输出段中。
 
4.    __used
定义在 include/linux/compiler-gcc4.h 中找到(根据编译器的不同,gcc4 中的 4 可能为 3)为:
# define __used          __attribute__((__used__))
 
5.      综合分析
由上面知道,initcall_t 是个用来函数指针定义类型,所以 __initcall_##fn##id 就是一个函数指针,fn 则是一个已经定义好了的函数。这里 ## 符号表示一个连接符的作用,它实际上负责一个新的函数名的定义。先不考虑 __used , __attribute__ 这些声明,假设fn 是一个定义好的函数 func() 的函数名 func,id 值为 9,level 值为 7,那么经过宏定义并展开后变成:
static initcall_t __initcall_func9


这时,再考虑 __used , __attribute__ 这些声明的意义:
__attribute__((__section__(".initcall" level ".init"))) 表示,函数(以上面的 __initcall_func9 为例)被放在 .initcall7.init 这个 section 中;__used 表示使用  .initcall7.init 这个 section 中的空间       
上面宏定义并不直接使用,同样在 init.h 文件中找到如下的宏定义:
 
#define early_initcall(fn)      __define_initcall("early",fn,early)
 
/*
 * A "pure" initcall has no dependencies on anything else, and purely
 * initializes variables that couldn't be statically initialized.
 *
 * This only exists for built-in code, not for modules.
 */
#define pure_initcall(fn)       __define_initcall("0",fn,0)
 
#define core_initcall(fn)       __define_initcall("1",fn,1)
#define core_initcall_sync(fn)     __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)      __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn)       __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)     __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)     __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn)   __define_initcall("4s",fn,4s)
#define fs_initcall(fn)         __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)       __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)     __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)     __define_initcall("6",fn,6)
#define device_initcall_sync(fn)   __define_initcall("6s",fn,6s)
#define late_initcall(fn)       __define_initcall("7",fn,7)
#define late_initcall_sync(fn)     __define_initcall("7s",fn,7s)
 
#define __initcall(fn) device_initcall(fn)
这些宏定义是为了方便使用 __define_initcall 宏的,上面每条宏第一次使用时都会产生一个新的输入段。
 
6.    linker scripts

linux-2.6.35.4/include/asm-generic/vmlinux.lds.h
 
#define INITCALLS                      \
    *(.initcallearly.init)                    \
    VMLINUX_SYMBOL(__early_initcall_end) = .;        \
    *(.initcall0.init)                     \
    *(.initcall0s.init)                    \
    *(.initcall1.init)                     \
    *(.initcall1s.init)                    \
    *(.initcall2.init)                     \
    *(.initcall2s.init)                    \
    *(.initcall3.init)                     \
    *(.initcall3s.init)                    \
    *(.initcall4.init)                     \
    *(.initcall4s.init)                    \
    *(.initcall5.init)                     \
    *(.initcall5s.init)                    \
    *(.initcallrootfs.init)                   \
    *(.initcall6.init)                     \
    *(.initcall6s.init)                    \
    *(.initcall7.init)                     \
    *(.initcall7s.init)

阅读(1137) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~