在Huawei Liteos源码中,比较核心的东西就是双向链表,它贯穿了整个内核代码,在研究内核功能实现前,需要对该数据结构及其对应的接口有一个比较清晰的认知,接下来开始学习 Liteos 中的双向链表。 该数据结构的定义和接口全部都实现在《los_list.h》文件中,而且所有该数据结构的API都是用 LITE_OS_SEC_ALW_INLINE 内联进行定义,因为这些接口在内核中大量的被调用,使用内联可以极大的提高内核的效率。
双向链表的定义在 los_list.h 文件中,其中所有接口都是在H文件中通过内联函数来实现的。
typedef struct LOS_DL_LIST { struct LOS_DL_LIST *pstPrev; /* 指向前一个节点 */ struct LOS_DL_LIST *pstNext; /* 指向后一个节点 */ } LOS_DL_LIST;从该数据结构中可以看出,该数据结构是双向链表的数据结构,链表中每个节点都有指向前一个和后一个节点的指针。双向链表的有点就是从任何一个节点开始,都可以通过遍历的方式找到该链表中任意一个节点。
说明:该接口是负责初始化链表的,并使得本节点中的两个指针均指向自己,初始化了双向链表的头。 上图为该数据结构的图形化示意,该双向链表的 HEAD 节点作为使用 LOS_ListInit 接口初始化的头结点。
说明: 该接口用于将一个新的 node 节点添加进list链表中 由该方法的实现可知:
该链表是将 list 节点作为链表的开始该链表中 list->pstNext 指向的是该链表中最后一个插入的节点如图下所示: 如果采用 LOS_ListAdd 方式添加一个节点,那么 node 节点会添加到最上面,也就是说 HEAD->pstNext指向的节点,就是新添加的节点。说明:将node节点插入到链表尾端,如下图所示:
说明:将pstNode节点从链表中删除,如下图所示:
说明:该接口用来判断 pstNode 是否为空双向链表,从 LOS_ListInit 接口可知,如果 pstNode->pstNext == pstNode 则该链表为空链表。
为什么在看源码之前需要先读懂 LOS_DL_LIST 数据结构呢?是因为该数据结构贯穿了整个内核源码,我们知道,LiteOS 内核中有任务调度,内存管理、定时器、中断等,就拿任务调度来说,内核为了实现内核调度,设置了很多的双向链表结构,这样方便操作系统去遍历哪些任务在就绪,哪些任务被阻塞等等,这些功能的实现,都是通过 LiteOS 提供的 LOS_DL_LIST 增删过程来完成的。所以在读内核源码之前,一定要搞清楚这这些接口的实现,对照着上面的图来想,这样在读源码的时候就会减少很多困扰。