宏定义
#if defined与#ifdef的区别:
#if defined 与#if !defined后可以加表达式。#ifdef与#ifndef后面不可以加表达式。
#if defined A && !defined B
printf("1");
#endif
宏连接符
#define czg(x) #@x //czg(3) = '3' 字符常量
#define czg(x) #x //czg(3) = "3" 字符串
#defineczg(x,y) x##y //:czg(love,9728)= love9728
__attrubute__()关键词
是一个编译器指令,告诉编译器声明的特性,或者让编译器进行更多的错误检查和高级优化,
# define __visible __attribute__((__externally_visible__))
externally_visible:附加到全局变量或函数的该属性使整个程序命令行选项,因此该对象在当前编译单元外部任然可见,如果 -整个程序 与 -flto和 gold被用作连接体插件, externally_visible属性被自动地添加到功能。对于其他无法生成解析文件的链接器,externally_visible仍然需要显式属性。
externally_visible的作用就是使该对象在当前编译单元外部仍然可见。
# define __iomem __attribute__((noderef, address_space(2)))
主要用于编译器的检查,检查地址空间的有效性。
noderef:必须是非解除参考,即这个变量地址必须是有效的
address_space(2):变量所在的地址空间必须是2,即io存储空间。0,1,2,3分别对应内核空间、用户空间、io存储空间、cpu空间
弱函数:
一般会有一个同名的函数,编译时会自动编译另一个函数,若没有,则编译弱函数。
void __weak fun(){}
printf输出格式:
%06x:以16进制输出,输出字符至少占据6个字符,若不够则左边填0
%6x:以16进制输出,输出字符至少占据6个字符,若不够则左边填空格
%p:可输出指针地址
__init fun(){}函数前__init含义:
__init宏告诉编译器,将变量或函数放在一个特殊的区域(在vmlinux.lds中被定义),该区域在.init.text这个代码区。__initdata将数据放在“.init.data”这个数据区中。标记为初始化的函数,该函数只能在初始化期间使用,在模块装载后,就会将初始化函数扔掉,这样可以将该函数占用的内存释放。
__exit宏告知编译器,将函数放在".exit.text"这个区域,__exitdata宏则放在".exitdata"这个区域,exit.*区域仅仅对模块是有用的:如果编译稳定的话,exit函数将永远不会被调用,只有当模块支持无效的时候,exit.*区域将被丢弃。
函数或符号前加EXPORT_SYMBOL的作用:
是对全部内核代码公开,不用修改内核代码就可以在内核模块中直接调用。
使用方法:在模块函数定义之后使用"EXPORT-SYMBOL(函数名)"来声明,在调用该函数的另外一个模块中使用extern对之声明,先加载定义该函数的模块,再加载调用该函数的模块。