linux内核链表的移植与使用

Posted on 2015-02-16 17:54  Bumble_Bee  阅读(640)  评论(0编辑  收藏  举报

一、
   Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲。由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用。

/*********************************** 
文件名:kernel link list of linux.h
作者:Bumble Bee
日期:2015-1-31 
功能:移植linux内核链表 
************************************/

/*链表结点数据结构*/
struct list_head 
{
    struct list_head *next, *prev;
};

/***********************************
函数名:  INIT_LIST_HEAD
参数:    指向list_head结构体的指针
返回值:  无
函数功能:通过将前向指针和后向指
          针指向自己来创建一个链表表
          头
***********************************/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

/***********************************
函数名:  __list_add
参数:    @new:要插入结点的指针域
          @prev:前一个节点的指针域
          @next:后一个节点的指针域
返回值:  无
函数功能:在两个已知节点中插入新节点
***********************************/

static inline void __list_add(struct list_head *new,
                  struct list_head *prev, struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}
extern void __list_add(struct list_head *new,
               struct list_head *prev, struct list_head *next);

/**************************************
函数名:  list_add
参数:    @new:要插入结点的指针域
          @head:要插入链表表头的指针域
返回值:  无
函数功能:在已知链表头部插入新节点
**************************************/

static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}


/**************************************
函数名:  list_add_tail
参数:    @new:要插入结点的指针域
          @head:要插入链表表头的指针域
返回值:  无
函数功能:在已知链表尾部插入新节点
**************************************/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}

/*************************************
函数名:  list_for_each
参数:    @pos:遍历链表的光标
          @head:要遍历链表的表头
返回值:  无
函数功能:实质为一个for循环,遍历链表
*************************************/
#define list_for_each(pos, head) \
    for (pos = (head)->next;pos != (head); \
        pos = pos->next)


/*************************************************
函数名:  list_entry
参数:    @ptr:节点中list_head的地址
          @type:节点的类型
          @member:list_head 在结构体中成员的名字
返回值:  节点的地址,已被强制转化为type型指针
函数功能:将节点最低位置假设为0,此时取成员member
          的地址即为offset,再用list_head的地址将
          offset减去即为节点的地址
**************************************************/
#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)


static inline void __list_del(struct list_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);
}

二、设计应用程序测试链表

/**************************** 
文件名:homework.c
作者:Bumble Bee
日期:2015-1-31 
功能:测试移植的linux内核链表 
*****************************/

#include <stdio.h>
#include "kernel link list of linux.h"

struct score
{
    int num;
    int english;
    int math;
    struct list_head list;
};

struct score stu1,stu2,stu3,*temp;

struct list_head score_head,*pos;

int main()
{
    INIT_LIST_HEAD(&score_head);                    //创建链表函数

    stu1.num = 1;
    stu1.english = 0;
    stu1.math = 0;
    list_add_tail(&(stu1.list),&(score_head));

    stu2.num = 2;
    stu2.english = 1;
    stu2.math = 1;
    list_add_tail(&(stu2.list),&(score_head));

    stu3.num = 3;
    stu3.english = 2;
    stu3.math = 2;
    list_add_tail(&(stu3.list),&(score_head));

    list_del(&(stu2.list));

    list_for_each(pos,&(score_head))
    {
        temp = list_entry(pos,struct score,list);
        printf("No %d,english is %d,math is %d\n",temp->num,temp->english,temp->math);
    }

    return 0;

}

三、运行结果