Linux2.6内核中链表的实现

对于一个计算机专业的学生,链表这种数据结构对我们来说再熟悉不过了,毕竟在大学的《数据结构》中就讲解过,相信你也自己实现过,它实现起来可能是这个样子:(这里的例子都来自《Linux内核设计与实现》第三版)

      假定我们有一个数据结构来描述犬科动物中的一员

[cpp]  view plain copy print ?
  1. struct fox  
  2. {  
  3.     unsigned long tail_length;  
  4.     unsigned long weight;  
  5.     bool          is_fantastic;  
  6. }  
       存储这个结构到链表里的通常方法是在数据结构中嵌入一个链表指针,比如:

[cpp]  view plain copy print ?
  1. struct fox  
  2. {  
  3.     unsigned long tail_length;  
  4.     unsigned long weight;  
  5.     bool          is_fantastic;  
  6.     struct fox    *next;  
  7.     struct fox    *prev;  
  8. }  


       由此得到的链表就像是这样:

Linux2.6内核中链表的实现_第1张图片
      Linux内核方式与众不同,它不是将数据结构塞入链表,而是将链表节点塞入数据结构!
      1.链表数据结构

      在过去,内核中有很多链表的实现,该选一个既简单,又高效的链表来统一它们了。

      链表代码在头文件<linux/list.h>中声明,其数据结构很简单:

[cpp]  view plain copy print ?
  1. struct list_head  
  2. {  
  3.     struct list_head *next;  
  4.     struct list_head *prev;  
  5. }  
       next指针指向下一个链表节点,prev指针指向前一个。然而,似乎这里还看不出它们有多大的作用。到底声明才是链表存储的具体内容呢?其实关键在于理解 list_head 结构是如何使用的。

      

[cpp]  view plain copy print ?
  1. struct fox  
  2. {  
  3.     unsigned long tail_length;  
  4.     unsigned long weight;  
  5.     bool          is_fantastic;  
  6.     struct list_head   list;  
  7. }  
       上述结构中,fox 中的list.next指向下一个元素,list.prev 指向前一个元素。现在链表已经能用了,但是显然还不够方便。因此内核又提供了一组链表操作例程。比如list_add()方法加入一个新的节点到链表中。但是,这些方法都有一个统一的特点:它们只接受 list_head 结构作为参数。使用宏 container_of() 我们可以很方便的从链表指针找到父结构中包含的任何变量。这是因为在 C 语言中,一个给定结构中的变量偏移在编译时地址就被ABI固定下来了。

你可能感兴趣的:(Linux2.6内核中链表的实现)