linux内核源码的技巧

时间:2021-03-21 12:27:43

http://blog.csdn.net/njufeng/article/details/29902287


看内核代码时,有些语言成分或者说编程技巧平常没见过更没用过,这里先记下一些:


1. 关于保留字前后都加上“__”,比如__inline__,其实等价于inline。C语言支持一些属性描述符,而gcc同样支持不少这样的描述符,这些描述符的使用等于在C语言中增加了一些新的保留字,此时,原来的C语言中这些词可能并不是保留字,一旦老的代码中刚好有变量名与此描述符一样,就会冲突。为了解决这个问题,才有了前后的“__”。


2. 宏定义中,随处可见,"#define   ...  do{...}while(0)"这样的宏定义,乍一看,do while不是多此一举嘛。其实不然,举个例子:

fs/proc/kcore.c中有这样的定义:

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. #define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)  

如果,我们这么用这个宏:

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. if()  
  2. DUMP_WRITE  
  3. else  
  4. ...  

很明显,程序执行的流程不是我们想要的。

此时,又会想,宏定义加个大括号不就完了。其实还是不然,同样的if语句:

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. if()  
  2. DUMP_WRITE  
  3. else  
  4. ...  

else前面的;时就认为if语句结束了。还是会有问题。


了解了这些,也就能理解一些空操作了。比如:

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. #define prepare_to_switch()     do { } while(0)  

3. 关于链表队列的实现。平常我们使用链表,无非是定义一个结构体,包含我们需要的有用数据,再加上个结构体指针指向下一个结构体即可。如:

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. typedef struct ex  
  2. {  
  3.     int value;  
  4.     struct ex* next;  
  5.     ...  
  6. };  

然后为这种数据结构写一套加入链表,从列表移除等操作函数。而内核里有太多的数据时使用链表队列来存储,如果这样的话,得写多少套列表操作函数可想而知。。。

所以,linux内核采用了一套通用的一般的可以用到各种不同的数据结构的队列操作。内核代码把next从结构体抽出来成为一个独立的数据结构list_head;

[cpp]  view plain copy linux内核源码的技巧 linux内核源码的技巧
  1. struct list_head {  
  2.     struct list_head *next, *prev;  
  3. };  

如果需要某种数据结构的队列,在结构内部放上一个list_head结构体即可。