您的位置:首页 > 其它

内核双链表-2

2015-10-08 20:41 288 查看
内核双链表:
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: