Linux内核链表的移植与使用

一、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 
#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;
}

三、运行结果

Linux内核链表的移植与使用_第1张图片

转自:https://www.cnblogs.com/51qianrushi/p/4294406.html

你可能感兴趣的:(linux)