Linux内核链表
来源:互联网 发布:mac环境变量在哪 编辑:程序博客网 时间:2024/06/04 18:24
一、简介
链表是一种常用的数据结构,它通过指针将一系列数据节点连接成一条数据链。相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据。链表的开销主要是访问的顺序性和组织链的空间损失。
通常链表数据结构至少包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系。按照指针域的组织以及各个节点之间的联系形式,链表又可以分为单链表、双链表、循环链表等多种类型。
二、内核链表
在Linux内核中使用了大量的链表结构来组织数据。这些链表大多采用了[include/linux/list.h]中实现的一套链表数据结构。
1. 定义
链表数据结构的定义:
struct list_head{ struct list_head *next, *prev;};
list_head结构包含两个指向list_head结构的指针prev和next,由此可见,内核的链表具备双链表功能,实际上,通常它都组织成双向循环链表。
传统的链表,指针的类型会随着节点struct的类型改变而改变,带数据域的链表降低了链表的通用性,不容易扩展;而Linux内核链表中,指针的类型固定不变都是 stuct list_head*。
2. 链表操作
初始化链表头
/* * Simple doubly linked list implementation. * * Some of the internal functions ("__xxx") are useful when * manipulating whole lists rather than single entries, as * sometimes we already know the next/prev entries and we can * generate better code by using them directly rather than * using the generic single-entry routines. */#define LIST_HEAD_INIT(name) { &(name), &(name) }// 实例化list_head,并通过结构体直接赋值方式初始化#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list;}
从链表头插入节点(插入头节点时)
/** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * 在heah节点后面插入new节点,适用于实现栈 * This is good for implementing stacks. */static inline void list_add(struct list_head *new, struct list_head *head){ // 在head和head->next之间插入new节点 __list_add(new, head, head->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;}
从链表尾插入节点(插入头节点时)
/** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * 在heah节点前面插入new节点,适用于实现队列 * This is useful for implementing queues. */static inline void list_add_tail(struct list_head *new, struct list_head *head){ __list_add(new, head->prev, head);}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;}
删除节点
static inline void list_del(struct list_head *entry){ __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2;}/* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */static inline void __list_del(struct list_head * prev, struct list_head * next){ next->prev = prev; prev->next = next;}
提取数据结构
/** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. * 已知数据结构(type型)中的节点指针ptr,找出数据结构 */#define list_entry(ptr, type, member) \ container_of(ptr, type, member)
遍历
/** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. * pos指向以head节点开头的链表里的每一个节点 */#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
3. 应用例子
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/list.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("XY");MODULE_DESCRIPTION("List Module");MODULE_ALIAS("List module");struct student{ cahr name [100]; int num; struct list_head list;};struct student *pstudent;struct student *tmp_student;struct list_head student_list;struct list_head *pos;int mylist_init(){ int i =0; INIT_LIST_HEAD(&student_list); pstudent = kmalloc(sizeof(struct student)*5,GFP_KERNEL); memset(pstudent,0,sizeof(struct student)*5); for(i=0;i<5;i++) { sprintf(pstudent[i].name,"Student%d",i+1); pstudent[i].num = i+1; list_add(&(pstudent[i].list),&student_list); } list_for_each(pos,&student_list) { tmp_student=list_entry(pos,struct student,list); printk("<0>student %d name: %s\n",tmp_student->num,tmp_student->name); } return 0;}void mylist_exit(){ int i; for(i=0;i<5;i++) { list_del(&(&pstudent[i].list)); } kfree(pstudent);}module_init(mylist_init);module_exit(mylist_exit);
阅读全文
0 0
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- Linux内核链表
- linux内核链表
- linux 内核链表
- Mob短信验证
- 初识Impala
- 快速排序
- 解决Listview通过addHeaderView方式头部添加轮播,轮播失效
- FileInputStream读取properties系统找不到指定的路径
- Linux内核链表
- xml应用rss的使用
- Unity热更新代码
- css的transform和transition属性
- 求(1~n)个数中1的个数
- 最大数问题 oj92
- web自动化测试第7步:模拟键盘事件(Keys)
- Unity制作SurvivalShooter游戏
- Tensorflow-简介