Linux内核使用的GNUC扩展_内联函数


投资自己,什么时候都不晚。


和Unix一样,Linux内核也是用C语言实现的。谈到C,几乎所有的人都会立即想到ANSIC标准。但是Linux内核的实现,其实并不完全符合ANSI C标准。实际上,内核开发者总会使用许多gcc提供的C语言的扩展部分。内核开发者使用的C语言涵盖了ISO C99标准和GNU C的扩展特性,我想,其中让人感兴趣的,应该不在于C99标准上,而是在于它的GNU C扩展特性上。下面,我们就一起来学内核使用的GNU C扩展特性吧。

1.内联函数

  • GNU的C编译器支持内联函数,这一点和ANSI标准完全不一样。在ANSI C中是没有inline这个关键字的。内联函数会在函数调用的地方直接把函数体展开,这样就可以减少函数调用的开销了(寄存器(现场)的保存和恢复)。而且,由于编译器会把调用函数的代码和函数本身的代码放在一起优化,所以也会有进一步优化代码的可能。
  • 当然,天底下没有白吃的午餐,这样做也是有代价的,那就是生成的代码会变长,这就意味着你必须使用更多的内存空间或更多的指令缓存来执行代码。
  • 内核开发者通常把那些对时间要求较高,而本身长度又较短的函数定义成内联函数。当然了,对于大块头的程序,你想把它定义成内联函数也没人反对。只不过,有这必要么?
  • 定义一个内联函数,需要使用static作为关键字,并且用inline限定它。如:
    ​​​static inline void foo(){...}​​ 内联函数必须在使用之前就定义好,否则编译器没法儿将之展开。由于使用static关键字进行限制,编译时不会为内联函数单独建立一个函数体。
  • 内联函数一般定义在头文件中,当然了,如果你仅仅在某个源文件中使用内联函数,也可以把它定义在源文件的开头部分。
  • 在内核中,为了类型安全的原因,优先使用内联函数而不是复杂的宏。

2.内联汇编