本文简单介绍Zephyr的链表的分类和区别,不涉及具体操作.
概述
任何一个操作系统的实现都会大量使用到链表,因此在代码实现级别上链表都会被独立成一个模块方便共用。这一点在zephyr上也一样.
zephyr的提供单向链表和双向链表的实现,均放在include/sys/下的头文件内,链表使用宏和函数操作,函数是static定义在头文件中,所以不同的moudle都有自己的链表代码。
单向链表
单向链表分为两种,一种是普通的单向链表,一种是带flag的单向链表
slist
Single-linked list,源文件在include/sys/slist.h
数据结构
每个节点sys_snode_t只含有指向下一个节点的指针next
链表sys_slist_t包含两个sys_snode_t指针分别指向单向链表得头和尾
1 | struct _snode { |
sflist
flag Single-linked list,源文件在include/sys/sflist.h
sflist也是一个单链表,和flist唯一不同的是该链表的每个节点可以记录一个flag
数据结构
每个节点sys_sfnode_t只含next_and_flags, 对于32/64位系统上结构体会默认4字节对齐,因此指针最低的2位可以被忽略,被用借用做为flag
链表sys_sflist_t包含两个sys_sfnode_t指针分别指向单向链表得头和尾
1 | typedef u32_t unative_t; |
flag操作
sflist由于链表指针的最低两位被作为flag,因此对指针和flag的操作会与slist不一样
1 | #define SYS_SFLIST_FLAGS_MASK 0x3UL |
单向链表操作差异
slist和sflist二者只有在flag上的差异,因此在节点上的操作二者都是一致的,zephyr中又抽象出了include/list_gen.h, slist和sflist关于节点的操作均是使用该头文件提供的宏生成,例如节点的插入
1 | static inline void sys_sflist_insert(sys_sflist_t *list, |
本文不展开分析list_gen.h,有兴趣的小伙伴可以去看源代码,里面其实就是单向列表的操作。
双向链表
双向链表由头文件include/sys/dlist.h提供,数据结构如下, 一个节点含有next和prev分别指向前一个节点和后一个节点
对于头节点,前一个节点是尾节点,对于尾节点后一个节点是头节点
1 | struct _dnode { |
双向链表的操作的API也实现在include/sys/dlist.h中,接收节点指针之间的操作,这里不展开了。