Advertisement

linux内核经典宏定义,Linux内核常见宏定义

阅读量:

我们在阅读Linux内核是,常见到这些宏 __init, __initdata, __initfunc(),

asmlinkage, ENTRY(), FASTCALL()等等。它们定义在 /include/linux/init.h 和

/include/linux/linkage.h 以及其他一些.h 文件中。

1. __init

位置:/include/linux/init.h

定义: #define __init attribute ((section (".init.text")))

该标识符与函数声明并置使用,则表明编译器在构建程序时必须将此函数放置于.text.init字段中

中,而这个Section 在内核完成初始化之后,就会被释放掉。

举例:asmlinkage void __init star_kerne(void) { ... }

__init__标记用于表示内核启动时使用的初始化代码,在内核启动后将不再发挥作用,并且其修饰的内容应放置于.init.text字段中。

section中,#define __init __section(.init.text) __cold notrace

其典型用法如下:

static int __init xxx_drv_init(void)

{

return pci_register_driver(&xxx_driver);

}

根据上面的定义与用法,xxx_drv_init()函数将会被link到.init.text段。

之所以加入这样的宏,原因有2:

其中一部分内核初始化机制基于该kernel将负责实现启动所需的init函数,并将其划分为七个级别

别,core_initcall, postcore_initcall, arch_initcall, subsys_initcall,

fs_iitcall, device_initcall,

late_initcall。按照从高到低的顺序排列着这7个级别。具体而言,它们依次进行:首先是core_initcall……最后是late_initcall。

2).显著提升系统效率。初始化代码的核心特性在于其在启动过程中执行特定任务,并在任务完成之后立即释放内存资源以减少占用。

driver中的使用:

module_init,

由module_exit函数调用的一类函数应分别运用__init与__exit进行标记;而PCI Driver数据结构则无需做任何标记。

probe函数被标记为__devinit;当remove函数被标记为__devexit时,在pci_DRV结构中引用其返回值。

2. __initdata

位置:/include/linux/init.h

定义:#define __initdata attribute ((section

(".init.data")))

标识符与变量声明并列放置,在编译过程中意味着gcc要求将该变量放置于.data.init字段中

Section中,而这个Section 在内核完成初始化之后,会释放掉。

举例:static struct kernel_param raw_params[] __initdata ={ ...

}

3. __initfunc()

位置:/include/asm-i386/init.h

定义:#define __initfunc(__arginit) \ __arginit __init; \

__arginit

注释:__initfunc() 是一个自定义宏,用来定义一个 __init

函数,在Linux-2.4中已被__init宏所取代。

举例:__initfunc (void mem_init(unsigned long start_mem, unsigned

long end_mem)) { ... }

4. asmlinkage

位置:/include/linux/linkage.h

定义:#define asmlinkage CPP_ASMLINKAGE attribute((regparm(0)))

注释:这个符号和函数声明排列在一起,并且带regparm(0)的属性说明告诉编译器该函数无需使用寄存器传输参数

gcc编译器在汇编过程中调用c语言函数时传递参数有多种方式:其中一种是通过堆栈实现的。通常情况下,默认会采用寄存器进行参数传递。如果要在你的汇编程序中使用堆栈来传递参数,则需特别配置相应的接口或寄存器以支持这种数据传输方式。

在编写程序的过程中调用C语言函数,并希望使用堆栈来传递参数。所定义的C函数应在函数体开始前预先声明并使用该宏asmlinkage。

举例:asmlinkage void __init start_kernel(void) { ... }

5.ENTRY()

位置:/include/linux/linkage.h

定义:#define ENTRY(name) \

.globl name; \

ALIGN; \

name:

注释:将name 声明为全局,对齐,并定义为标号。

举例:

ENTRY(swapper_pg_dir)

6. FASTCALL ()

位置:/include/linux/kernel.h

定义:#define FASTCALL(x) x attribute((regparm(3)))

将该标志符与函数声明结合放置在一起,并在编译器中指定regparm(3)属性时会告知编译器该函数可通过寄存器传递最多三个参数(EAX、EDX等三个寄存器)

与 ECX 相关。只有当较多参数被传递时。从而降低了压栈弹出操作的数量。调用速度显著提高

举例:extern void FASTCALL(__switch_to(struct task_struct *prev,

struct task_struct *next))

这个例子中,prev将通过eax,next通过edx传递。

7. __sched

位置:/include/linux/sched.h

定义: #define __sched attribute((section(".sched.text")

全部评论 (0)

还没有任何评论哟~