数据结构之Linux Kernel双向链表(一)
来源:互联网 发布:淘宝网小狗用品 编辑:程序博客网 时间:2024/05/17 22:24
Linux Kernel双向链表
链表是Linux Kernel中最简单的数据结构。
常规链表 的使用 是将数据结构塞入链表中,Linux Kernel中 链表的使用比较独特 ,是将链表节点塞入数据结构中。通过遍历链表 再通过相对位移 找到数据结构。
6、遍历大结构体
参考:Linux内核设计与实现第三版
链表是Linux Kernel中最简单的数据结构。
常规链表 的使用 是将数据结构塞入链表中,Linux Kernel中 链表的使用比较独特 ,是将链表节点塞入数据结构中。通过遍历链表 再通过相对位移 找到数据结构。
Linux Kernel中,链表代码在头文件<linux/list.h>中申明。
struct list_head { struct list_head *prev; struct list_head *next;};next指针指向下一个链表节点,prev指针指向前一个节点。
在使用的时候 嵌入到自己的数据结构中。
struct test_node { int a; char b; struct list_head list; /* 链表 */};上例中 test_node中的list.next指向下一个元素,list.prev指向前一个元素。这样 所有的元素 都通过list链表连起来了。
那么如何通过遍历list链表找到真正可以用的数据结构(a和b)呢?
内核中通过container_of()宏实现
#define offsetof(type , member)( (size_t)(&((type*)0)->member) )
@type为数据结构 结构体类型。
@member是type结构体中的成员。
offsetof宏是求得成员member相对于type结构体的首地址的偏移量
#define container_of(ptr, type, member)( (type*)((size_t)ptr - offsetof(type, member)) )
@ptr 是指向大结构体中member成员的指针
@type 是大结构体的类型
@member 是大结构体中的某个成员的名字
container_of宏 是根据大结构体中的某个成员的地址,求得大结构体的首地址这样Linux Kernel 提供了链表各种最基本的操作方法,而不需要知道list_head所嵌入对象的数据结构。所以不同的数据结构都可以使用Linux 内核链表。
Linux 内核链表常用操作有:
1、初始化链表
static void INIT_LIST_HEAD(struct list_head *list){ list->prev = list; list->next = list;}2、插入链表
static void __list_add(struct list_head *list, struct list_head *prev_node, struct list_head *next_node){ list->prev = prev_node; list->next = next_node; prev_node->next = list; next_node->prev = list;}头插
static void list_add(struct list_head *list, struct list_head *head){ __list_add(list, head, head->next);}尾插
static void list_add_tail(struct list_head *list , struct list_head *head){ __list_add(list, head->prev, head);}3、删除节点
static void list_del(struct list_head *list){ list->prev->next = list->next; list->next->prev = list->prev; INIT_LIST_HEAD(list);//指向自己}4、判断是否为空
static int list_is_empty(struct list_head *list){ return list->next == list;}
5、遍历链表
#define list_for_each(cur, head) \for(cur = (head)->next; (cur) != (head); cur = (cur)->next)安全遍历
#define list_for_each_safe(cur, tmp, head) for(cur = (head)->next, tmp = (cur)->next; (cur) != (head); cur = (tmp), tmp = (tmp)->next )
6、遍历大结构体
#define list_for_each_entry(ptr, head, member) for( ptr = container_of((head)->next, typeof(*(ptr)), member); &((ptr)->member) != (head); \ ptr = container_of((ptr)->member.next, typeof(*(ptr)), member) )
参考:Linux内核设计与实现第三版
0 0
- 数据结构之Linux Kernel双向链表(一)
- linux内核数据结构之双向循环链表struct list_head(一)
- 数据结构之双向链表(SplDoublyLinkedList)
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- 数据结构之双向链表
- linux内核数据结构之双向循环链表struct list_head
- linux内核里的数据结构之双向链表
- linux kernel 中的链表(一)
- nginx高级数据结构源码分析(一)-----双向链表
- 详解Linux内核之双向循环链表(一)
- 双向循环链表在 LINUX kernel 中的实现
- 【九度】题目1539:师弟
- flash rom ram
- Linux系统学习
- CFBundleVersion与CFBundleShortVersionString
- 你是一个努力工作的程序员,还是一个懒惰的程序员?
- 数据结构之Linux Kernel双向链表(一)
- c++ 变量
- parted创建硬盘分区并创建LVM
- js 时间格式与时间戳的相互转换示例代码
- 动态规划入门之01背包
- linux下db4.x-util的安装问题,终于成功了(Ubuntu)
- Android 针对ListActivity中ListView 点击事件和长按事件
- HtmlAgilityPack中通过sibling才能得到对应的InnerText和form,option等tag的子节点
- iOS 删除文件夹下所有文件的方式