linux 应用程序使用struct list_head链表,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;

}

三、运行结果

afec3f3679a4e2d7ffb08a64cc3133a3.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值