在阅览源码的进程中,我发现许多的代码中都采用了链表,链表的也是十分有意义的一种。有咱们在C言语中运用的那种数据嵌套指针的方法。也有在linux中将链表作为一个独自的目标,然后将这个目标嵌入到不同的目标中,然后依据container_of()得到对应的目标指针。这些方法都是常用的方法之一。
在看uC/OS-II中我阅览源码时发现其间居然很少有关于链表的操作。开端也没有细心的去剖析原因,我乃至以为位图的方法替代了链表。由于uC/OS-II基本上可以使命是根据数组等静态内存散布的方法,全局变量的方法可以经过位图简略的链接在一起。
可是在阅览事情标志组的进程中我发现其间仍是存在许多关于链表的操作的,比方许多的如何将事情标志节点链接起来,可是剖析源码并没有
typedef struct { /* Event Flag Wait List Node */
void *OSFlagNodeNext; /* Pointer tonextNODE in wait list */
void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */
void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */
void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */
OS_FLAGS OSFlagNodeFlags; /* Eventflagto wait on */
INT8U OSFlagNodeWaitType; /* Type of wait: */
/* OS_FLAG_WAIT_AND */
/* OS_FLAG_WAIT_ALL */
/* OS_FLAG_WAIT_OR */
/* OS_FLAG_WAIT_ANY */
} OS_FLAG_NODE;
#endif
从上面的代码可以发现并没有运用OS_FLAG_NODE的指针方法,而是采用了void *的指针方法,结合详细的完成进程我发现这样的界说方法的确比较咱们之前传统的界说方法存在许多的长处,首要这种衔接方法比传统的链接方法愈加的灵敏多变,并必定指向的内容便是自己界说的这种结构体,由于void *这种万能的指针方法扩展了对不同类型的链接才能,使得链表的优势愈加的显着。
pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /* Add node at beginning of eventflagwait list */
pnode->OSFlagNodePrev = (void *)0;
pnode->OSFlagNodeFlagGrp = (void *)pgrp; /* Link to Event Flag Group */
pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
if (pnode_next != (void *)0) { /* Is this the first NODE to insert? */
pnode_next->OSFlagNodePrev = pnode; /* No, link in doubly linked list */
}
pgrp->OSFlagWaitList = (void *)pnode;
上面是我从源码中仿制出来的部分代码其间就有这种链表的操作方法,可以发现这种void*的类型扩展了链接目标的规模。但相同需求留意的时,在编写代码的进程中需求强制类型转化,也便是链接到链表中时需求转化为void *类型,而当弹出链表以后又需求转化成数据自身的结构类型,这或许导致一些问题的发生。可是void *类型的指针的确可以完成不同目标之间的链接联系。这就相似于在linux中的嵌入式链表十分的相似。
强制类型转化是在运用void *时特别留意的事项。