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 <stdio.h>
#include "homework.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;

}

三、运行结果

  

时间: 2024-10-23 17:36:53

linux内核链表的移植与使用的相关文章

linux内核链表使用

原文链接:http://blog.csdn.net/xnwyd/article/details/7359373 Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下: struct A{ int property; struct list_head p; } 其中,list_head结构类型定义如下: struct list_head { struct list_head *next,*prev; };

第32课 Linux内核链表剖析

1. Linux内核链表的位置及依赖 (1)位置:{linux-2.6.39}\\include\linux\list.h (2)依赖 ①#include<linux\types.h> ②#include<linux\stddef.h> ③#include<linux\poison.h> ④#include<linux\prefetch.h> 2. 移植及注意事项 (1)清除文件间的依赖:剥离依赖文件中与链表实现相关的代码 (2)清除与平台相关代码(GNU

Linux 内核链表

一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_del:删除节点 5.list_entry:取出节点 6.list_for_each:遍历链表 2.程序代码

例说Linux内核链表(二)

链表使用 我认为熟悉内核链表功能最好的方法就是看一些简单的实例,实例是一个非常好的素材去更好的理解链表. 下面是一个例子,包含创建,添加,删除和遍历链表. <span style="font-size:14px;"><span style="color:#330099;">#include <stdio.h> #include <stdlib.h> #include "list.h" struct

Linux 内核 链表 的简单模拟(2)

接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. */ #define list_for_each(pos, head) for (pos = (head)->next; pos != (head);

例说Linux内核链表(一)

介绍 众所周知,Linux内核大部分是使用GNU C语言写的.C不同于其他的语言,它不具备一个好的数据结构对象或者标准对象库的支持.所以可以借用Linux内核源码树的循环双链表是一件很值得让人高兴的事. 在include/linux/list.h文件中用C实现了一个好用的循环链表.它是有效而且易于操作的,否则它也不会被内核使用(译者注:在kernel中大量的使用了循环双链表结构,比如在在进程描述符实体中我们就可以看到很多struct list_head的身影).不管何时,依靠这种结构,在内核中都

例说Linux内核链表(三)

经常使用的linux内核双向链表API介绍 linux link list结构图例如以下: 内核双向链表的在linux内核中的位置:/include/linux/list.h 使用双向链表的过程,主要过程包括创建包括struct link_head结构的结构体(item),建立链表头.向链表中加入item(自己定义数据结构.双向链表数据单元).删除链表节点.遍历链表,判空等. 1.建立自己定义链表数据结构 struct kool_list{ int to; struct list_head li

Linux内核,文件系统移植过程中出现的一些问题与解决办法

1.bootm地址和load address一样 此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行.因此此时的entry point必须设置为load address + 0x40.如果kernel boot过程没有到uncompressing the kernel,就可能是这里设置不对. boom address == load address == entry point - 0x40 2.

linux内核链表的使用

linux内核链表:链表通常包括两个域:数据域和指针域.struct list_head{struct list_head *next,*prev;};include/linux/list.h中实现了一套精彩的链表数据结构.传统的链表指针指向下一个节点的头部.linux链表指针指向下一个指针list_head结构(*next),双向循环.不会随着外部数据的变化而变化,使它具有通用性.? -------------------------------------------------------