转载:http://my.chinaunix.net/space.php?uid=25052030&do=blog&id=65337
Linux内核的链表机制简单易用,而且与特写的结构分离,具有一整套的链表接口。不需要人为的根据特定的结构而编写相应的链表处理方法,是一种很好的机制。
为什么要将linux内核的链表机制应用于用户态呢。这主要是在做项目的时候的经验教训。因为做的项目,有大量的链表操作。初期我使用的是类似于数据结构书中介绍的那种链表机制,如图所示。
struct data
{
int a;
struct data *prev;
struct data *next;
};
用这种格式的话,对于每一个结构都要编写相应的链表处理函数。即使用相关函数来统一实现,也不便于理解,所以就彩用的内核中的链表结构,大大的减少了代码量。
新的结构如下
struct data、、
{
int a;
struct list_head list;
};
相应的操作时限是对list_head结构进行的。下面是我自已写的一个小的测试程序,但对链表的合并等相关代码,还没有加进去。
list_head.h文件
#include <stdio.h>
#include <stdlib.h>
//分配空间并初使化链表头
#define LIST_HEAD_INIT(name) {&(name),&(name)}//作用??????????????
#define LIST_HEAD(name) struct list_head name= LIST_HEAD_INIT(name)
//对已经分配了空间的list头指针进行初使化
#define INIT_LIST_HEAD(ptr) do {/
(ptr)->next = (ptr);/
(ptr)->prev = (ptr);/
}while(0)
//链表结构
struct list_head
{
struct list_head *prev;
struct list_head *next;
};
//获得包含list的相应结构(由链表结点到数据项对象)
#define list_entry(ptr,type,member) container_of(ptr,type,member)
#define container_of(ptr,type,member) ({/
const typeof(((type *)0)->member)* __mptr = (ptr);/
(type *)((char *)__mptr - offsetof(type,member));})
#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
list_head.c文件
#include "list_head.h"
//临时测试结构
struct test
{
int a;
struct list_head list;
};
struct list_head test_head;
//在prev和next之间插入一个新的结点new
static inline void in_list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{
prev->next = new;
new->next = next;
new->prev = prev;
next->prev = new;
}
//删除prev和next之间的结点
static inline void in_list_del(struct list_head *prev,struct list_head *next)
{
prev->next = next;
next->prev = prev;
}
//清空链表
static inline int list_empty(const struct list_head *head)
{
return head->next==head;
}
//在链表头插入结点
static inline void list_add(struct list_head *new,struct list_head *head)
{
in_list_add(new,head,head->next);
}
//在链表尾插入结点
static inline void list_add_tail(struct list_head *new,struct list_head *head)
{
in_list_add(new,head->prev,head);
}
//删除结点
static inline void list_del(struct list_head *entry)
{
in_list_del(entry->prev, entry->next);
}
//测试删除结点
int test_del_entry(int a)
{
struct list_head *ptr;
struct test *entry;
for (ptr = test_head.next; ptr != &test_head; ptr = ptr->next)
{
entry = list_entry(ptr, struct test, list);
if (entry->a == a)
{
list_del(&entry->list);
free(entry);
return 0;
}
}
return -1;
}
、、//删除整个链表
while( 0 == list_empty(head))、、传入链表的空头
{
struct list_head *p;
p = head;
p = p->next;
linklist_view = list_entry (p,linknode_me,list);//linklist linklist_view;我的结构体指针,linknode我的结构节点
printk ();
list_del (p);
kfree(linklist_view);
}
//测试在链表尾插入结点
void test_add_entry_down(struct test *new)
{
struct list_head *ptr;
struct test *entry;
for (ptr = test_head.next; ptr != &test_head; ptr = ptr->next)
{
entry = list_entry(ptr, struct test, list);
if (entry->a > new->a)
{
list_add_tail(&new->list, ptr);
return;
}
}
list_add_tail(&new->list, ptr);
return;
}
//测试在链表头插入结点
void test_add_entry_up(struct test *new)
{
struct list_head *ptr;
struct test *entry;
for (ptr = test_head.next; ptr != &test_head; ptr = ptr->next)
{
entry = list_entry(ptr, struct test, list);
if (entry->a < new->a)
{
list_add_tail(&new->list, ptr);
return;
}
}
list_add_tail(&new->list, ptr);
return;
}
//输出结点
void test_print_allentry(struct list_head *head)
{
struct list_head *ptr;
struct test *entry;
for (ptr = head->next; ptr != head; ptr = ptr->next)
{
entry = list_entry(ptr, struct test, list);
printf("**********%d**********/n",entry->a);
}
return;
}
//测试
int main(void)
{
INIT_LIST_HEAD(&test_head);
struct test *tmp;
tmp = (struct test*)malloc(sizeof(struct test));
tmp->a = 5;
test_add_entry_down(tmp);
tmp = (struct test*)malloc(sizeof(struct test));
tmp->a = 3;
test_add_entry_down(tmp);
tmp = (struct test*)malloc(sizeof(struct test));
tmp->a = 2;
test_add_entry_down(tmp);
tmp = (struct test*)malloc(sizeof(struct test));
tmp->a = 6;
test_add_entry_down(tmp);
tmp = (struct test*)malloc(sizeof(struct test));
tmp->a = 4;
test_add_entry_down(tmp);
int ff = 2;
test_del_entry(ff);
test_print_allentry(&test_head);
ff = 4;
test_del_entry(ff);
test_print_allentry(&test_head);
ff = 5;
test_del_entry(ff);
test_print_allentry(&test_head);
return 0;
}