Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541976
  • 博文数量: 64
  • 博客积分: 1591
  • 博客等级: 上尉
  • 技术积分: 736
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-08 14:54
文章分类

全部博文(64)

文章存档

2011年(42)

2010年(22)

分类: LINUX

2010-12-31 13:31:44

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 

#include 

//分配空间并初使化链表头

#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;

}

//测试在链表尾插入结点

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;

}

阅读(3447) | 评论(0) | 转发(0) |
0

上一篇:深入分析 Linux 内核链表

下一篇:ioctl接口

给主人留下些什么吧!~~