返回

鸿蒙轻内核 M 核源码剖析:数据结构篇 — 任务排序链表

闲谈

在鸿蒙轻内核 M 核中,任务排序链表是一个至关重要的数据结构,它负责管理任务的执行顺序,在任务延迟到期或超时唤醒等场景下发挥着不可或缺的作用。深入剖析其源码,有助于我们理解鸿蒙轻内核的任务管理机制。

任务排序链表:任务管理的关键

任务排序链表在鸿蒙轻内核 M 核中扮演着任务管理的关键角色。它是一个链表结构,每个节点代表一个任务,节点之间按照任务的执行顺序相连。

链表的头部指向最早执行的任务,尾部指向最晚执行的任务。当任务需要执行时,系统从链表头部开始遍历,依次执行每个任务。任务完成后,系统将对应的节点从链表中删除。

延迟到期和超时唤醒场景

任务排序链表的应用场景主要集中在任务延迟到期和超时唤醒方面:

  • 延迟到期: 当任务执行需要延迟一段时间时,系统将任务插入到链表中的指定位置,使其在指定时间后执行。
  • 超时唤醒: 当任务在指定时间内未完成执行时,系统将任务从链表中唤醒,重新执行。

通过这种机制,鸿蒙轻内核可以高效地管理任务的执行顺序,确保任务在正确的时间执行,避免任务延时或遗漏。

源码剖析:深入理解实现细节

鸿蒙轻内核 M 核任务排序链表的源码位于 /kernel/sched/queue/list.h/kernel/sched/queue/list.c 文件中。

数据结构

typedef struct List {
    uint32_t size;
    ListNode *head;
    ListNode *tail;
} List;

typedef struct ListNode {
    ListNode *next;
    ListNode *prev;
    Task task;
    uint32_t expire_time;
} ListNode;

List 结构体代表任务排序链表,包含链表的大小、头部和尾部节点。ListNode 结构体代表链表中的每个节点,包含指向下一个节点和前一个节点的指针、任务信息以及任务执行的到期时间。

初始化和插入操作

任务排序链表的初始化和插入操作如下:

List list_init() {
    List list;

    list.size = 0;
    list.head = NULL;
    list.tail = NULL;

    return list;
}

ListNode *list_insert(List *list, Task task, uint32_t expire_time) {
    ListNode *node = malloc(sizeof(ListNode));
    node->next = NULL;
    node->prev = NULL;
    node->task = task;
    node->expire_time = expire_time;

    if (list->size == 0) {
        list->head = node;
        list->tail = node;
    } else {
        ListNode *curr = list->head;
        while (curr->next != NULL && curr->expire_time < expire_time) {
            curr = curr->next;
        }

        if (curr == list->tail) {
            list->tail->next = node;
            node->prev = list->tail;
            list->tail = node;
        } else {
            node->next = curr->next;
            node->prev = curr;
            curr->next = node;
            if (node->next != NULL) {
                node->next->prev = node;
            }
        }
    }

    list->size++;

    return node;
}

list_init() 函数初始化一个任务排序链表,list_insert() 函数将任务及其执行到期时间插入到链表中。插入时,函数遍历链表找到适当的位置,将新节点插入到该位置,保持链表中任务的执行顺序。

遍历和删除操作

任务排序链表的遍历和删除操作如下:

void list_foreach(List *list, void (*func)(ListNode *node)) {
    ListNode *curr = list->head;
    while (curr != NULL) {
        func(curr);
        curr = curr->next;
    }
}

void list_remove(List *list, ListNode *node) {
    if (node == list->head) {
        list->head = node->next;
        if (list->head != NULL) {
            list->head->prev = NULL;
        }
    } else if (node == list->tail) {
        list->tail = node->prev;
        if (list->tail != NULL) {
            list->tail->next = NULL;
        }
    } else {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

    free(node);
    list->size--;
}

list_foreach() 函数遍历链表中的每个节点,并将每个节点传递给指定的回调函数。list_remove() 函数删除指定的节点,更新链表的头部、尾部和节点的连接关系。

结语

鸿蒙轻内核 M 核任务排序链表是一个高效且易于维护的数据结构,在任务管理中扮演着至关重要的角色。通过对源码的深入剖析,我们不仅了解了其数据结构和算法的实现细节,还理解了其在任务延迟到期和超时唤醒场景中的应用。这些知识将有助于开发者深入理解鸿蒙轻内核的任务管理机制,为构建高效可靠的嵌入式系统奠定基础。