1)uCOS-III内核中的链表大多是不循环的双向链表(有头有尾),在插入和删除操作时,要考虑特殊情况(比如插入表头、插入表尾等特殊情况)。
而freertos内核中的链表为双向循环链表,并引入了xListEnd保证了链表永远非空,所以每个元素的插入和删除都是作为表中的一般元素(非表头和表尾)进行的,操作效率要高一些
在这里插入代码片
#include <stdio.h>
typedef struct pend_data PEND_DATA;
struct pend_data{
PEND_DATA * prev;
PEND_DATA * next;
int prio;
};
typedef struct pend_list PEND_LIST;
struct pend_list{
PEND_DATA * head;
PEND_DATA * tail;
int num;
};
void list_insert_prio(PEND_LIST * list, PEND_DATA * data)
{
PEND_DATA * nn = NULL;
if (list->num == 0) {
list->num = 1;
data->prev = NULL;
data->next = NULL;
list->head = data;
list->tail = data;
} else {
list->num ++;
nn = list->head;
while(nn) {
if (data->prio > nn->prio)
break;
else {
nn = nn->next;
}
}
if (nn == NULL) {
// at tail
PEND_DATA * tmp = list->tail;
list->tail = data;
data->next = NULL;
data->prev = tmp;
tmp->next = data;
} else {
if (nn->prev == NULL) {
// at first
PEND_DATA * tmp = list->head;
list->head = data; data->prev = NULL;
data->next = tmp;
tmp->prev = data;
}else {
// between
PEND_DATA * tmp = nn->prev;
tmp->next = data;
data->prev = tmp;
data->next = nn;
nn->prev = data;
}
}
}
}
int main()
{
PEND_LIST list1 = {NULL, NULL, 0};
PEND_DATA d1 = {NULL, NULL, 3};
PEND_DATA d2 = {NULL, NULL, 1};
PEND_DATA d3 = {NULL, NULL, 2};
list_insert_prio(&list1, &d1);
list_insert_prio(&list1, &d2);
list_insert_prio(&list1, &d3);
printf("num = %d\n", list1.num);
PEND_DATA * tmp = list1.head;
while(tmp){
printf("prio = %d\n", tmp->prio);
tmp = tmp->next;
}
}
2)在消息投递时,如果有任务在消息队列的pend列表中等待,uC/OS-III的做法是直接将该消息post给等待的任务并把它就绪,整个消息不会经过消息队列。而FreeRTOS的做法是将该消息放置到消息队列中,然后检查是否有任务正等待接收消息,如果有,就将其就绪,由就绪的任务去主动获取该消息。
FreeRTOS的做法实现了投递消息与取出消息的解耦,但这带来了一个问题,就是当某个任务投递完一个消息,并使A任务就绪了,而在A任务执行前,又有一个高优先级的B任务从这个消息队列中取出了该消息,那么A任务在以后试图从消息队列中取出消息时,会出现失败,这是FreeRTOS中所有内核对象的pend操作都可能会出现的情况,内核的做法是会重新计算超时时间,只要没超时,就重新阻塞(按新的阻塞时间),这种设计会降低内核的执行效率。在uC/OS-III中,每一次的消息post操作,要么消息被post到了消息队列上,要么消息被post给了任务,操作结果是明确的,操作过程是高效的。
原文链接:https://blog.csdn.net/weixin_41213648/article/details/88249890