Linux内核之数据结构--链表
来源:互联网 发布:淘宝买电动车哪家 编辑:程序博客网 时间:2024/06/15 23:39
前言
Linux内核实现了一下常用的内建数据结构,主要有:
- 链表
- 队列
- 映射
- 二叉树
今天详细学习一下链表的知识,链表是一种存放和操作可变数量元素(常称为节点)的数据结构。Linux内核的标准链表就是采用环形双向链表形式实现的。
链表数据结构
传统的链表是将数据存放在链表节点中;而Linux内核的方式与众不同,它的链表节点只有两个指针(prev和next),链表节点保存在用户数据结构中。
链表代码在头文件< linux/list.h>中声明,数据结构很简单:
struct list_head { struct list_head *next; struct list_head *prev;}
next指针指向下一个链表节点,prev指向上一个链表节点。然后这个链表节点list_head一般保存在数据的结构体内:
struct fox{ unsigned long tail_length; //尾巴长度 unsigned long weight; //重量 bool is_fantastic; //狐狸是否奇妙? struct list_head list; //链表节点存放在此处}
这样在以后对链表的操作都是针对链表节点list_head进行的,然后根据list_head就可以找到其所在的数据结构,这是通过list_entry()函数实现的:
list_entry(ptr,type,member);/*ptr是指向list_head类型的链表的指针type是数据的结构体,struct foxmember是数据结构体中的一个域,类型为list_head函数的作用就是根据结构的成员指针找到其所在结构体的指针。*/
声明和初始化一个链表
Linux提供了两种方式初始化链表。
一种是使用LIST_HEAD()这个宏:
#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)
LIST_HEAD(fox_list);就是定义并初始化了名为fox_list的链表,链表头为fox_list,其next、prev指针都指向自己。
另一种是先定义list_head指针变量,然后用INIT_LIST_HEAD()将其初始化为链表:
struct fox *red_fox;red_fox=kmalloc(sizeof(*red_fox),GFP_LERNEL);red_fox->tail_length=40;red_fox->weigth=6;red_fox->is_fantastic=false;INIT_LIST_HEAD(&red_fox->list);//注意参数为指针
添加和删除节点
向链表中添加一个节点:
list_add(struct list_head *new, struct list_head *head);例:list_head(&fox->list, &fox_list);//fox是新建的数据结构体,fox_list是之前初始化的链表
把节点增加到链表尾:
list_add_tail(struct list_head *new, struct list_head *head);
从链表中删除一个节点:
list_del(struct list_head *list);例:list_del(&fox->list);
注意,该删除操作并不会释放list或包含list的结构体所长用的内存。仅仅是将其从链表中移除。
从链表中删除一个节点并对其初始化:
list_del_init(struct list_head *list);
把节点从一个链表移动到另一个链表:
list_move(struct list_head *list, struct list_head *head);//把list项从链表中移除,并添加到另一个链表的head节点后面
把节点从一个链表移动到另一个链表的末尾:
list_move_tail(struct list_head *list, struct list_head *head);
检查链表是否为空:
list_empty(struct list_head *head);
若链表为空返回非0值,否则返回0。
合并两个链表:
list_splice(struct list_head *list, struct list_head *head);list_splice_init(struct list_head *list, struct list_head *head);//合并后初始化原来的链表
将list指向的链表插入到指定的链表head节点后面。
遍历链表
最简单的方法就是使用list_for_each()宏遍历链表,再通过list_entry()获取完整数据结构体
例:
struct list_head *p;struct fox *f;list_for_each(p, &fox_list){ f=list_entry(p, struct fox, list);}
以上两个函数可以合并为一个:list_for_each_entry()
struct fox *f;list_for_each_entry(f, &fox_list, list){ //f就遍历了所有的数据结构体;}
反向遍历链表:
list_for_each_entry_reverse(pos, head, member);
遍历的同时安全删除节点:
list_for_each_entry_safe(pos, next, head, member);
- Linux内核之数据结构--链表
- 深入浅出linux之内核数据结构
- linux内核数据结构之kfifo
- linux内核数据结构之kfifo
- linux内核数据结构之kfifo
- 深入浅出Linux之内核数据结构
- linux内核数据结构之kfifo
- linux内核数据结构之kfifo
- Linux内核之数据结构--队列
- Linux内核之数据结构--映射
- linux内核数据结构之kfifo
- linux内核数据结构之kfifo
- 深入浅出linux之内核数据结构
- linux内核数据结构之kfifo
- linux内核数据结构---链表(1)
- Linux内核数据结构—链表
- Linux内核数据结构之链表
- linux内核数据结构之链表
- hdu 2768 Cat vs. Dog(最大独立集)
- 算法竞赛入门经典3.2 分子量UVa1586
- 数组的排序算法
- iOS 排序算法总结—冒泡排序
- Linux 网络常见报错及监控项
- Linux内核之数据结构--链表
- sg函数 poj 2960 S-Nim
- POJ 1543 暴搜
- django简单入门
- bmob实现短信验证功能
- 随机数的使用
- Java多线程
- CodeForces 670D2 Magic Powder - 2
- 输入数字n,按顺序打印出1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。