要研究LINUX内核,C语言是基础中的基础,但是LINUX并不是完全的标准C,而是对标准C做了很多扩展,这些扩展特性对于我们分析内核有着很重要的作用,下面做些总结性的工作。
9、特殊属性声明
GNU C允许声明函数、变量和类型的特殊属性,以便进行手工的代码优化和定制代码检查的方法。
- no return属性用于函数,表示该函数从不返回。这可以让编译器生成稍微优化的代码,最重要的是可以消除不必要的警告信息比如未初使化的变量。例如:
//include/linux/kernel.h
#define ATTRIB_NORET __attribute__((noreturn))...
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;
- format(ARCHETYPE,STRING-INDEX,FIRST-TO-CHECK)属性用于函数,表示该函数使用
printf,scanf或strftime风格的参数,使用这类函数最容易犯的错误是格式串与参数不匹配,指定format属性可以让编译器根据格式串检查参数类型。例如:
//include/linux/kernel.h
asm linkage int printk(const char* fmt, ...)__attribute__((format(printf,1,2)));
表示第一个参数是格式串,从第二个参数起根据格式串检查参数。
unused属性用于函数和变量,表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。
section("section-name")属性用于函数和变量,通常编译器将函数放在.text区,变量放在.data区或.bss区,使用section属性,可以让编译器将函数或变量放在指定的节中。例如:
//include/linux/init.h
#define __init __attribute__((__section__(".text.init")))
#define __exit __attribute__((unused,__section__(".text.exit")))
#define __init data__attribute__((__section__(".data.init")))
#define __exit data__attribute__((unused,__section__(".data.exit")))
#define __initsetup __attribute__((unused,__section__(".setup.init")))
#define __init_call __attribute__((unused,__section__(".initcall.init")))
#define __exit_call __attribute__((unused,__section__(".exitcall.exit")))
连接器可以把相同节的代码或数据安排在一起,Linux内核很喜欢使用这种技术,例如系统的初始
化代码被安排在单独的一个节,在初始化结束后就可以释放这部分内存。
- aligned(ALIGNMENT)属性用于变量、结构或联合类型,指定变量、结构域、结构或联合的对齐量,以字节为单位,例如:
//include/asm-i386/processor.h
struct i387_fxsave_struct{
unsigned short cwd;
...
}__attribute__((aligned(16)));
表示该结构类型的变量以16字节对齐。通常编译器会选择合适的对齐量,显示指定对齐通常是由于体系限制、优化等原因。
- packed属性用于变量和类型,用于变量或结构域时表示使用最小可能的对齐,用于枚举、结构或联合类型时表示该类型使用最小的内存。例如:
//include/asm-i386/desc.h
struct Xgt_desc_struct{
unsigned short size;
unsigned long address__attribute__((packed));
};
域address将紧接着size分配。属性packed的用途大多是定义硬件相关的结构,使元素之间没有因
对齐而造成的空洞。
===========我是华丽的分割线===========
更多知识:
点击关注专题:嵌入式Linux & ARM
或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1
或扫描二维码: