内核数据结构
- 链表
- 队列
- 映射
- 二叉树
1. 链表
与c语言相同,链表就是一个指向下一个元素指针的结构组成的数据链。在这里需要强调的是linux内核源码的设计方法。
#include <linux/list.h>
- list_head 定义
struct list_head
{
struct list_head *next;
struct list_head *prev;
};
linux 上的双向链表就这样,没有数据部分
- 实际数据结构定义
struct data_type
{
struct list_head list;
char *data;
};
- list_entry 宏定义
#define list_entry(ptr,type,member) \
((char*)ptr-(&(char*)(((type*)0))->member))
- list_entry 使用
data_type *p = list_entry(plist,data_type,list);
实际上就是根据成员变量和首地址的偏移来计算的。如果知道成员变量的地址,就可以根据: 首地址 = 成员地址-偏移大小 来计算
- 接口函数
list_add 增加元素
list_add_tail
list_del 删除元素
list_del_init 删除元素,
list_move
list_move_tail
list_empty
list_splice 合并链表
list_splice_init
list_for_each_entry
list_for_each_entry_reverse
2. 队列
#include <linux/kfifo.h>
kernel/kfifo.c
入口偏移:下一次入队列时的位置
出口偏移:下一次入队列的位置
- 创建队列
int kfifo_alloc(struct kfifo *fifo, unsigned int size,gfp_t gfp_mask);
或
void kfifo_init(struct kfifo *fifo,void *buffer,unsigned int size);/*size 为buffer大小*/
- 推入数据
unsigned int kfifo_in(kfifo* ,void *from,int len);
- 摘取数据
int kfifo_out
kfifo_out peek /*只是获取数据,不删除队列里的数据*/ - 其它
kfifo_size
kfifo_is_empty
kfifo_is_full
kfifo_avail //还有多少空间
kfifo_reset //撤销内容
kfifo_free
3. 映射
每个键必然关联唯一一个值
实现方式:散列表 和二叉搜索树
二叉搜索树的优势:
- 在最差的情况下会有更好的表现,对数复杂性相比线性复杂性
- 保证了顺序
- 不需要散列函数
4. 二叉树
- 二叉搜索树(BST)
- 自平衡二叉搜索树
- 红黑树
红黑树
lib/rbtree.c
<linux/rbtree.h>
六个属性
1. 所有节点要么红色要么黑色
2. 叶子都是黑色
3. 叶子节点不包含数据
4. 非叶子节点都有两个子节点
5. 如果一个节点是红色的,它的子节点都是黑色的
6. 一个节点到其叶子节点的路径中,如果总是包含同样数目的黑色节点,则该路径相比其它路径是最短的(最长是红黑交替的)
实践: 弄清楚为什么这样。