Linux 系统编程:几个宏定义
__init宏使内建模块中的init函数在执行完成后释放掉,仅用于初始化。编译器将所有代码存储到特殊的内存段中,初始化结束就释放这段内存。
__initdata,和__init的作用基本上一样,不过它是针对数据。
__exit和__exitdata 仅用于退出和关闭线程,一般在注销设备驱动程序时使用。
likely和unlikely 的实现:#define likely(x) __builtin_expect(!!(x),1)#define unlikely(x) __builtin_expect(!!(x),0)
__builtin_expect() 是编译器来预测分之。
通知程序链// notifier_block 对象链表。
include/linux/notifier.h struct notifier_block { int(*notifier_call)(struct notifier_block *self, unsigned long, void *); struct notifier_block *next; 指向链中的下一个通知块。 int priority; 优先级声明};
#define __define_initcall(level,fn,id) \ static initcall_t __initcall_##fn##id __attribute_used__ \ __attribute__ ((__section__(".initcall" level ".init"))) = fn这条宏带有3个参数:level,fn, id。1.用来定义类型为initcall_t的static函数指针,函数指针的名称由参数fn和id决定:__initcall_##fn##id,这就是函数指针的名称,它其实是一个变量名称。利用宏的参数产生名称。
2. __attribute__ ((__section__ (".initcall" level ".init"))),输入段的名称由level决定,如果level="1",则输入段是.initcall1.init,如果level="3s",则输入段是.initcall3s.init。这一函数指针变量就是放在用这种方法决定的输入段中的。
3. 函数指针变量的初始值其实就是宏参数fn,实际使用中,fn其实就是真实定义好的函数。一般用法如下:#define pure_initcall(fn) __define_initcall("0",fn,0)#define core_initcall(fn) __define_initcall("1",fn,1)
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))asmllinkage这个标志符和函数声明放在一起,告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。