内核双链表-2

内核双链表:

  3.1这里的双链表程序是很简单,也是使用了许多宏和内联函数,我们现在主要来看下程序。内核中双链表的结构体定义如下:

structlist_head {

         struct list_head *next, *prev;

}; 这里的头部只有两个指针域,相当奇怪,我们平时定义的链表主要都是节点域与指针域。这里这么用,自然有好处,将指针直接与数据剥离,对于内核中拥有不同数据域的链表即可公用一套指针域。现在这是我能想到的。不然前面的container_of宏也没有多大意义了。

 

3.2程序接下来进行数据的初始化

#defineLIST_HEAD_INIT(name) { &(name), &(name) }

 

#defineLIST_HEAD(name) \

         struct list_head name =LIST_HEAD_INIT(name)

 

#defineINIT_LIST_HEAD(ptr) do { \

         (ptr)->next = (ptr); (ptr)->prev= (ptr); \

} while(0)

这里主要是初始化头结点,假如有一个使用中的结构体,这里的代码即可进行宏替换。

第二个宏就类似于,structlist_head _head; _head={&(_head),&(head)}; 第三个即是将next和prev指针都指向本身。接下来看看头插法和尾插法的实现。

static  inline  void  __list_add(structlist_head *new,

                                  struct list_head *prev,

                                  struct list_head *next)

{

         next->prev = new;

         new->next = next;

         new->prev = prev;

         prev->next = new;

}

/*尾插法实现*/

static  inline  void list_add(struct list_head *new, structlist_head *head)

{

         __list_add(new, head, head->next);

}

/*头插法实现*/

static  inline  void list_add_tail(struct list_head *new,struct list_head *head)

{

         __list_add(new, head->prev, head);

}

其实也是比较简单,不过这里封装的很好。

 

3.3 接下来看看从链表中删除一个节点。

staticinline void __list_del(struct list_head * prev, struct list_head * next)

{

         next->prev = prev;

         prev->next = next;

}

staticinline void list_del(struct list_head *entry)

{

         __list_del(entry->prev,entry->next);

         entry->next = LIST_POISON1;

         entry->prev = LIST_POISON2;

}

由于这里是没有进行内存释放的,所以用户在自己使用时,一定要进行手动释放内存[自己定义的结构体],否则会出现野指针和内存泄露。

 

3.4 进行移动

/*移动到某节点头部*/

static  inline  void  list_move(struct  list_head *list, struct  list_head *head)

{

        __list_del(list->prev,list->next);

        list_add(list, head);

}

/*移动到某节点尾部*/

static  inline  void  list_move_tail(struct list_head *list,

                                       struct list_head *head)

{

        __list_del(list->prev,list->next);

        list_add_tail(list, head);

}

这两个思想都是一样,先删除,在插入。

 

3.5 进行链表的遍历

#definelist_for_each(pos, head) \

         for (pos = (head)->next,prefetch(pos->next); pos != (head); \

                 pos= pos->next, prefetch(pos->next))

其实也就是一个for循环,使用宏进行了重定义。

pos作为中间变量,依次递加,其中prefetch主要保证了地址的有效,还有这里面涉及到流的欲抓取,据说能够使用这个函数通常可以减少缓存缺失和停顿,没试验过,^_^||,前面的功能有点像assert

这里还实现了双向链表的前置扫描,这里不再赘述。

我们这里还有一个安全的链表遍历。这里何为安全,看下面代码。

#define list_for_each_safe(pos, n, head) \

         for(pos = (head)->next, n = pos->next; pos != (head); \

                   pos= n, n = pos->next)

举个例子就行,在list_for_each遍历的时候,你敢删除一个节点吗?

 

3.6接下来这个宏比较吊

#define list_for_each_entry(pos, head,member)                              \

         for(pos = list_entry((head)->next, typeof(*pos), member),   \

                        prefetch(pos->member.next);                          \

              &pos->member != (head);                                         \

              pos = list_entry(pos->member.next,typeof(*pos), member),      \

                        prefetch(pos->member.next))

仍然是遍历的过程。

pos = list_entry((head)->next,typeof(*pos), member), \

                        prefetch(pos->member.next);

首先是获取member成员所在节点pos的首地址。就是container_of宏的作用,然后prefetch告诉cpu接下来会获取下一个节点,达到预取的目的。

&pos->member != (head);      这个是用于循环条件判断。

pos = list_entry(pos->member.next,typeof(*pos), member),        \

                        prefetch(pos->member.next))

这个类似于第一个。

 

 

接下来我们使用这些个函数,实现简答的一些程序设计。[不可直接套用list.h]文件,这里很多函数都是内核态的,非用户态。  我们来删繁就简下。

double_list.h

#ifndef _double_list_

#define _double_list_

 

#include <stdio.h>

#include <stddef.h>

#include <stdlib.h>

 

#define LIST_POISON1  ((void *) 0x00100100)

#define LIST_POISON2  ((void *) 0x00200200)

 

/*用户结构体*/

typedef struct _TApple

{

  intweight;

  charcolor[10];

  charname[20];

}TApple;

 

 

struct list_head {

         TApple*pApple;

         structlist_head *next, *prev;

};

 

//#define LIST_HEAD_INIT(name) { &(name),&(name) }

 

//#define LIST_HEAD(name) \

         structlist_head name = LIST_HEAD_INIT(name)

 

#define INIT_LIST_HEAD(ptr) do { \

         (ptr)->next= (ptr); (ptr)->prev = (ptr); \

} while (0)

 

 

 

#define container(ptr, type, member) ({ \

       const typeof(((type*)0)->member)* __mptr =(ptr);  \

       (type*)((char*)__mptr - offsetof(type, member)); })

                  

 

static inline void __list_add(structlist_head *new,

                                  struct list_head *prev,

                                 struct list_head *next)

{

         next->prev= new;

         new->next= next;

         new->prev= prev;

         prev->next= new;

}

 

static inline void list_add(struct list_head*new, struct list_head *head)

{

         __list_add(new,head, head->next);

}

 

static inline void list_add_tail(structlist_head *new, struct list_head *head)

{

         __list_add(new,head->prev, head);

}

 

static inline void __list_del(structlist_head * prev, struct list_head * next)

{

         next->prev= prev;

         prev->next= next;

}

 

static inline void list_del(struct list_head*entry)

{

         __list_del(entry->prev,entry->next);

         entry->next= LIST_POISON1;

         entry->prev= LIST_POISON2;

}

 

#define list_for_each(pos, head) \

         for(pos = (head)->next, pos->next!=NULL; pos != (head); \

                 pos= pos->next)

                           

#define list_for_each_safe(pos, n, head) \

         for(pos = (head)->next, n = pos->next; pos != (head); \

                   pos= n, n = pos->next)

                  

#define list_for_each_entry_safe(pos, n,head, member)                        \

         for(pos = container((head)->next, typeof(*pos), member),   \

                   n= container(pos->member.next, typeof(*pos), member);   \

              &pos->member != (head);                                         \

              pos = n, n = container(n->member.next,typeof(*n), member))

 

#endif

 

 

double_list.c

#include "double_list.h"

 

int main()

{

         TApple*pApple = (TApple*)malloc(sizeof(TApple));

         memset(pApple,0x00, sizeof(TApple));

         pApple->weight= 10;

         strcpy(pApple->color,"红色");

         strcpy(pApple->name,"红色富士山");

        

         structlist_head* head_node = (struct list_head*)malloc(sizeof(struct list_head));

         INIT_LIST_HEAD(head_node);

         head_node->pApple= pApple;

         printf("pApple=%p,head_node=%p \n", pApple,head_node);

         /*untilnow, you can see a head node*/

         /************************************************************************/

         TApple*pApple1 = (TApple*)malloc(sizeof(TApple));

         memset(pApple1,0x00, sizeof(TApple));

         pApple1->weight= 10;

         strcpy(pApple1->color,"绿色");

         strcpy(pApple1->name,"绿色富士山");

        

         structlist_head* head_node1 = (struct list_head*)malloc(sizeof(struct list_head));

         head_node1->pApple= pApple1;

         list_add(head_node1,head_node);

         printf("pApple1=%p,head_node1=%p \n", pApple1,head_node1);

         /************************************************************************/

         TApple*pApple2 = (TApple*)malloc(sizeof(TApple));

         memset(pApple2,0x00, sizeof(TApple));

         pApple2->weight= 10;

         strcpy(pApple2->color,"黄色");

         strcpy(pApple2->name,"黄色富士山");

        

         structlist_head* head_node2 = (struct list_head*)malloc(sizeof(struct list_head));

         head_node2->pApple= pApple2;

         list_add(head_node2,head_node);

         printf("pApple2=%p,head_node2=%p \n", pApple2,head_node2);

         /***********************************************************************/

        

         structlist_head* step_pointer = NULL;

         structlist_head* temp_pointer = NULL;

         intidx = 0;

         list_for_each_safe(step_pointer,temp_pointer,head_node)

         {

                   printf("weight=[%d],color=[%s],  name=[%s]\n",step_pointer->pApple->weight,step_pointer->pApple->color,step_pointer->pApple->name);

                   printf("index=%d,step_pointer->pApple=%p, step_pointer=%p \n", idx,step_pointer->pApple,step_pointer);

                   free(step_pointer->pApple);

                   step_pointer->pApple=NULL;

                   free(step_pointer);

                   step_pointer= NULL;

                   idx++;

         }

         /*******************delhead**********************/

         printf("weight=[%d],color=[%s],  name=[%s]\n",head_node->pApple->weight,head_node->pApple->color,head_node->pApple->name);

         printf("index=%d,head_node->pApple=%p, head_node=%p \n", idx,head_node->pApple,head_node);

         free(head_node->pApple);

         head_node->pApple=NULL;

         free(head_node);

         head_node= NULL;

        

         return0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章