Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(2)任务模块

OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(2)任务模块

原创
作者头像
小帅聊鸿蒙
发布于 2025-05-21 12:42:28
发布于 2025-05-21 12:42:28
990
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

任务是操作系统一个重要的概念,是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。鸿蒙轻内核的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。本文我们来一起学习下任务模块的源代码,所涉及的源码,以OpenHarmony LiteOS-M内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_m 获取。

接下来,我们看下任务模块的结构体,任务初始化,任务常用操作的源代码。

1、任务模块的结构体定义

在文件kernel\include\los_task.h定义的任务控制块结构体LosTaskCB,源代码如下,结构体成员的解释见注释部分。

代码语言:shell
AI代码解释
复制
typedef struct {
    VOID                        *stackPointer;            /* 任务栈指针 */
    UINT16                      taskStatus;               /* 任务状态 */
    UINT16                      priority;                 /* 任务优先级 */
    INT32                       timeSlice;                /* 剩余的时间片 */
    UINT32                      waitTimes;
    SortLinkList                sortList;                 /* 任务超时排序链表节点 */
    UINT64                      startTime;
    UINT32                      stackSize;                /* 任务栈大小 */
    UINT32                      topOfStack;               /* 栈顶指针 */
    UINT32                      taskID;                   /* 任务编号Id */
    TSK_ENTRY_FUNC              taskEntry;                /* 任务入口函数 */
    VOID                        *taskSem;                 /* 任务持有的信号量 */
    VOID                        *taskMux;                 /* 导致任务阻塞的互斥锁 */
    UINT32                      arg;                      /* 任务入口函数的参数 */
    CHAR                        *taskName;                /* 任务名称 */
    LOS_DL_LIST                 pendList;                 /* 就绪队列等链表节点 */
    LOS_DL_LIST                 timerList;                /* 任务超时排序链表节点 */
    EVENT_CB_S                  event;
    UINT32                      eventMask;                /* 事件掩码 */
    UINT32                      eventMode;                /* 事件模式 */
    VOID                        *msg;                     /* 分给给队列的内存*/
    INT32                       errorNo;
} LosTaskCB;

另外一个比较重要的结构体是TSK_INIT_PARAM_S,创建任务时,需要指定任务初始化的参数。源代码如下,结构体成员的解释见注释部分。

代码语言:shell
AI代码解释
复制
typedef struct tagTskInitParam {
    TSK_ENTRY_FUNC       pfnTaskEntry;              /** 任务入口函数 */
    UINT16               usTaskPrio;                /** 任务参数  */
    UINT32               uwStackSize;               /** 任务栈大小 */
    CHAR                 *pcName;                   /** 任务名称  */
    UINT32               uwResved;                  /** 保留  */
} TSK_INIT_PARAM_S;

2、任务模块初始化

在系统启动时,在kernel\src\los_init.c中调用OsTaskInit()进行任务模块初始化,还会调用OsIdleTaskCreate()创建空闲任务。

2.1 任务模块初始化

函数OsTaskInit()定义在kernel\src\los_task.c,我们分析下这个函数的执行过程。

⑴处代码根据开发板配置的最大任务数g_taskMaxNum,计算需要申请的内存大小size,为任务控制块TCB数组(也叫作任务池)g_taskCBArray申请内存。为什么比最大任务数多申请一个呢?在删除任务时会使用。下文分析删除任务的源码时再详细讲解其用意。⑵处代码初始化双向链表g_losFreeTask用作空闲的任务链表、g_taskRecyleList可以回收的任务链表。⑶处循环初始化每一个任务,任务状态未使用OS_TASK_STATUS_UNUSED,初始化任务Id,并把任务挂在空闲任务链表上。

⑷处初始化全局变量LosTask g_losTask,该全局变量维护当前运行的任务和要调度执行的任务。初始化任务池时,设置当前运行的任务为g_taskCBArray[g_taskMaxNum]。⑸处空闲任务编号暂时设置为无效值,后续创建空闲任务时再设置空闲任务编号。

优先级队列,详细的代码实现剖析,参见之前的源码剖析文章。⑸处互斥锁死锁检测的调测特性的,后续系列文章专题进行讲解。⑹处代码初始化排序链表,详细的代码实现剖析,参见之前的源码剖析文章。⑺处如果开启了惰性栈,计算TCB的成员变量stackFrame在其结构体中的偏移量g_stackFrameOffLenInTcb

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
{
    UINT32 size;
    UINT32 index;

⑴  size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
    g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
    if (g_taskCBArray == NULL) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }
    (VOID)memset_s(g_taskCBArray, size, 0, size);

⑵  LOS_ListInit(&g_losFreeTask);
    LOS_ListInit(&g_taskRecyleList);for (index = 0; index <= LOSCFG_BASE_CORE_TSK_LIMIT; index++) {
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
        g_taskCBArray[index].taskID = index;
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);
    }

    // Ignore the return code when matching CSEC rule 6.6(4).
⑷  (VOID)memset_s((VOID *)(&g_losTask), sizeof(g_losTask), 0, sizeof(g_losTask));
    g_losTask.runTask = &g_taskCBArray[g_taskMaxNum];
    g_losTask.runTask->taskID = index;
    g_losTask.runTask->taskStatus = (OS_TASK_STATUS_UNUSED | OS_TASK_STATUS_RUNNING);
    g_losTask.runTask->priority = OS_TASK_PRIORITY_LOWEST + 1;

⑸  g_idleTaskID = OS_INVALID;return OsSchedInit();
}

2.2 创建空闲任务IdleCore000

除了初始化任务池,在系统启动阶段还会创建idle空闲任务。⑴处设置任务初始化参数时,空闲任务的入口执行函数为OsIdleTask()。⑵处调用函数把空闲任务状态设置为就绪状态。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
{
    UINT32 retVal;
    TSK_INIT_PARAM_S taskInitParam;
    // Ignore the return code when matching CSEC rule 6.6(4).
    (VOID)memset_s((VOID *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
⑴  taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;
    taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;
    taskInitParam.pcName = "IdleCore000";
    taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
    retVal = LOS_TaskCreateOnly(&g_idleTaskID, &taskInitParam);

    if (retVal != LOS_OK) {
        return retVal;
    }

⑵  OsSchedSetIdleTaskSchedPartam(OS_TCB_FROM_TID(g_idleTaskID));
    return LOS_OK;
}

我们看下空闲任务的入口执行函数为OsIdleTask(),它调用OsRecyleFinishedTask()回收任务栈资源,后文会分析如何回收任务资源。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
{
    while (1) {
        OsRecyleFinishedTask();
        HalEnterSleep(OS_SYS_DEEP_SLEEP);
    }
}

3、任务模块常用操作

3.1 创建和删除任务

3.1.1 创建任务

鸿蒙轻内核提供了2个创建任务的函数,有LOS_TaskCreateLOS_TaskCreateOnlyLOS_TaskCreateLOS_TaskCreateOnly的区别是,前者创建任务完毕就使任务进入就绪状态,并触发调度,如果就绪队列中没有更高优先级的任务,则运行该任务。后者只创建任务,设置任务状态为阻塞suspend状态,需要开发者去调用LOS_TaskResume使该任务进入ready状态。

函数LOS_TaskCreate代码如下,可以看出创建任务的时候,调用⑴处的函数LOS_TaskCreateOnly()来创建任务。创建任务后,执行⑵处的代码使任务进入ready就绪队列,如果系统启动完成,允许任务调度,则执行⑶触发任务调度。如果新创建的任务优先级最高,则会被调度运行。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *taskInitParam)
{
    UINT32 retVal;
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;

⑴  retVal = LOS_TaskCreateOnly(taskID, taskInitParam);
    if (retVal != LOS_OK) {
        return retVal;
    }
    taskCB = OS_TCB_FROM_TID(*taskID);

    intSave = LOS_IntLock();
#if (LOSCFG_BASE_CORE_CPUP == 1)
    g_cpup[taskCB->taskID].cpupID = taskCB->taskID;
    g_cpup[taskCB->taskID].status = taskCB->taskStatus;
#endif

⑵  OsSchedTaskEnQueue(taskCB);
    LOS_IntRestore(intSave);if (g_taskScheduled) {
        LOS_Schedule();
    }

    return LOS_OK;
}

我们接着分析下如何使用函数UINT32 LOS_TaskCreateOnly()创建任务。⑴处调用OsTaskInitParamCheck()检测创建任务的参数的合法性。⑵处调用函数回收释放的任务。⑶处如果任务池为空,无法创建任务,返回错误码。⑷处从任务池获取一个空闲的任务控制块taskCB,然后从空闲任务链表中删除。⑸处根据指定的任务栈大小为任务栈申请内存,⑹处判断任务栈内存申请释放成功,如果申请失败,则把任务控制块归还到空闲任务链表中,并返回错误码。⑺处调用函数初始化任务栈,更新任务控制块成员信息。详细见后面对该函数的分析。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *taskInitParam)
{
    UINTPTR intSave;
    VOID  *topOfStack = NULL;
    LosTaskCB *taskCB = NULL;
    UINT32 retVal;

    if (taskID == NULL) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

⑴  retVal = OsTaskInitParamCheck(taskInitParam);
    if (retVal != LOS_OK) {
        return retVal;
    }

⑵  OsRecyleFinishedTask();

    intSave = LOS_IntLock();if (LOS_ListEmpty(&g_losFreeTask)) {
        retVal = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
        OS_GOTO_ERREND();
    }

⑷  taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask));
    LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask));

    LOS_IntRestore(intSave);

#if (LOSCFG_EXC_HRADWARE_STACK_PROTECTION == 1)
    UINTPTR stackPtr = (UINTPTR)LOS_MemAllocAlign(OS_TASK_STACK_ADDR, taskInitParam->uwStackSize +
        OS_TASK_STACK_PROTECT_SIZE, OS_TASK_STACK_PROTECT_SIZE);
    topOfStack = (VOID *)(stackPtr + OS_TASK_STACK_PROTECT_SIZE);
#else
⑸      topOfStack = (VOID *)LOS_MemAllocAlign(OS_TASK_STACK_ADDR, taskInitParam->uwStackSize,
        LOSCFG_STACK_POINT_ALIGN_SIZE);
#endifif (topOfStack == NULL) {
        intSave = LOS_IntLock();
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
        LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_NO_MEMORY;
    }

⑺  retVal = OsNewTaskInit(taskCB, taskInitParam, topOfStack);
    if (retVal != LOS_OK) {
        return retVal;
    }

    *taskID = taskCB->taskID;
    OsHookCall(LOS_HOOK_TYPE_TASK_CREATE, taskCB);
    return retVal;

LOS_ERREND:
    LOS_IntRestore(intSave);
    return retVal;
}

我们看下创建任务函数调用的函数OsRecyleFinishedTask(),该函数在系统进入空闲时也会调用。删除运行状态的任务时,会把任务挂在双向链表里g_taskRecyleList。任务回收函数就用来回收此类任务,实现任务资源回收。我们分析下它的代码。⑴处循环遍历回收链表,⑵从回收链表获取第一个任务taskCB,从回收链表删除并插入到空闲任务链表里。任务栈保护在后续系列再深入分析,继续往下看代码,⑶处获取任务栈栈顶指针,接着调用内存释放函数来释放任务栈占用的内存,并设置任务栈的栈顶为空。

代码语言:shell
AI代码解释
复制
STATIC VOID OsRecyleFinishedTask(VOID)
{
    LosTaskCB *taskCB = NULL;
    UINTPTR intSave;
    UINTPTR stackPtr;

    intSave = LOS_IntLock();while (!LOS_ListEmpty(&g_taskRecyleList)) {
⑵      taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecyleList));
        LOS_ListDelete(LOS_DL_LIST_FIRST(&g_taskRecyleList));
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
#if (LOSCFG_EXC_HRADWARE_STACK_PROTECTION == 1)
        stackPtr = taskCB->topOfStack - OS_TASK_STACK_PROTECT_SIZE;
#else
⑶      stackPtr = taskCB->topOfStack;
#endif
        (VOID)LOS_MemFree(OS_TASK_STACK_ADDR, (VOID *)stackPtr);
        taskCB->topOfStack = (UINT32)NULL;
    }
    LOS_IntRestore(intSave);
}

我们继续分析下函数OsNewTaskInit(),⑴处调用函数初始化任务栈,上一系列已经分析过该函数,代码的其余部分用来更新任务控制块的成员信息,比如⑵处任务状态设置为阻塞状态。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 OsNewTaskInit(LosTaskCB *taskCB, TSK_INIT_PARAM_S *taskInitParam, VOID *topOfStack)
{
⑴  taskCB->stackPointer    = HalTskStackInit(taskCB->taskID, taskInitParam->uwStackSize, topOfStack);
    taskCB->arg             = taskInitParam->uwArg;
    taskCB->topOfStack      = (UINT32)(UINTPTR)topOfStack;
    taskCB->stackSize       = taskInitParam->uwStackSize;
    taskCB->taskSem         = NULL;
    taskCB->taskMux         = NULL;
⑵  taskCB->taskStatus      = OS_TASK_STATUS_SUSPEND;
    taskCB->priority        = taskInitParam->usTaskPrio;
    taskCB->timeSlice       = 0;
    taskCB->waitTimes       = 0;
    taskCB->taskEntry       = taskInitParam->pfnTaskEntry;
    taskCB->event.uwEventID = OS_NULL_INT;
    taskCB->eventMask       = 0;
    taskCB->taskName        = taskInitParam->pcName;
    taskCB->msg             = NULL;
    SET_SORTLIST_VALUE(&taskCB->sortList, OS_SORT_LINK_INVALID_TIME);
    return LOS_OK;
}
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
代码语言:erlang
AI代码解释
复制
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.OpenHarmonyUboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

3.1.2 删除任务UINT32 LOS_TaskDelete()

该函数根据传入的参数UINT32 taskId删除任务。我们分析下删除任务的源代码,⑴处检验传入的参数,⑵处如果任务还未创建,返回错误码。⑶处如果删除的任务正在运行,又处于锁任务调度情况下,打印信息,告诉用户不推荐在锁任务调度期间进行任务删除,然后执行⑷,把全局变量赋值0来解锁任务调度。

⑸处调用函数处理任务状态,如果处于就绪状态设置为非就绪状态,并从就绪队列删除。如果处于阻塞状态,从阻塞队列中删除。如果任务处于超时等待状态,从超时排序链表中删除。⑹恢复任务控制块事件相关的成员信息。⑺如果任务正在运行,设置任务为未使用状态,接着调用函数OsRunningTaskDelete()把任务放入回收链表,然后主动触发任务调度,稍后详细分析该函数。如果删除的任务不是出于运行状态,则执行⑻,设置任务为未使用状态,接着把任务回收到空闲任务链表里,然后获取任务栈的栈顶指针,调用内存释放函数释放任务栈的内存。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = OS_TCB_FROM_TID(taskID);
    UINTPTR stackPtr;

⑴  UINT32 ret = OsCheckTaskIDValid(taskID);
    if (ret != LOS_OK) {
        return ret;
    }

    intSave = LOS_IntLock();if ((taskCB->taskStatus) & OS_TASK_STATUS_UNUSED) {
        LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

    /* If the task is running and scheduler is locked then you can not delete it */
⑶  if (((taskCB->taskStatus) & OS_TASK_STATUS_RUNNING) && (g_losTaskLock != 0)) {
        PRINT_INFO("In case of task lock, task deletion is not recommended\n");
⑷      g_losTaskLock = 0;
    }

    OsHookCall(LOS_HOOK_TYPE_TASK_DELETE, taskCB);
⑸  OsSchedTaskExit(taskCB);

⑹  taskCB->event.uwEventID = OS_NULL_INT;
    taskCB->eventMask = 0;
#if (LOSCFG_BASE_CORE_CPUP == 1)
    // Ignore the return code when matching CSEC rule 6.6(4).
    (VOID)memset_s((VOID *)&g_cpup[taskCB->taskID], sizeof(OsCpupCB), 0, sizeof(OsCpupCB));
#endif
    if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
⑺      taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
        OsRunningTaskDelete(taskID, taskCB);
        LOS_IntRestore(intSave);
        LOS_Schedule();
        return LOS_OK;
    } else {
⑻       taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
#if (LOSCFG_EXC_HRADWARE_STACK_PROTECTION == 1)
        stackPtr = taskCB->topOfStack - OS_TASK_STACK_PROTECT_SIZE;
#else
        stackPtr = taskCB->topOfStack;
#endif
        (VOID)LOS_MemFree(OS_TASK_STACK_ADDR, (VOID *)stackPtr);
        taskCB->topOfStack = (UINT32)NULL;
    }

    LOS_IntRestore(intSave);
    return LOS_OK;
}

我们看下函数OsRunningTaskDelete()的源码。⑴处把当前运行的任务放入待回收链表里,然后执行⑵把当前运行的任务放入任务池的最后一个位置g_taskCBArray[g_taskMaxNum]。为什么这么操作呢?等后续分析源码的时候再来解答。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT STATIC_INLINE VOID OsRunningTaskDelete(UINT32 taskID, LosTaskCB *taskCB)
{
⑴  LOS_ListTailInsert(&g_taskRecyleList, &taskCB->pendList);
⑵  g_losTask.runTask = &g_taskCBArray[g_taskMaxNum];
    g_losTask.runTask->taskID = taskID;
    g_losTask.runTask->taskStatus = taskCB->taskStatus | OS_TASK_STATUS_RUNNING;
    g_losTask.runTask->topOfStack = taskCB->topOfStack;
    g_losTask.runTask->taskName = taskCB->taskName;
}

3.2 控制任务状态

3.2.1 恢复挂起的任务LOS_TaskResume()

恢复挂起的任务,使该任务进入就绪状态,和下文中的LOS_TaskSuspend()成对使用。⑴处获取任务的TCB,⑵处对任务状态进行判断,如果任务未创建或者非阻塞状态,则返回错误码。执行⑶设置任务状态为非挂起状态。⑶处获取任务的状态进行判断,如果任务没有创建或者不是挂起状态,则返回相应的错误码。 ⑷检查任务状态是否为OS_CHECK_TASK_BLOCK,即(OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND)中的一种,这几个状态影响恢复挂起的任务。如果非上述几个状态,执行⑸调用函数,把任务状态改为就绪状态,插入任务就绪队列。如果支持支持调度,则执行⑹触发调度。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;
    UINT32 retErr = OS_ERROR;

    if (taskID > LOSCFG_BASE_CORE_TSK_LIMIT) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

⑴  taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
    tempStatus = taskCB->taskStatus;if (tempStatus & OS_TASK_STATUS_UNUSED) {
        retErr = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    } else if (!(tempStatus & OS_TASK_STATUS_SUSPEND)) {
        retErr = LOS_ERRNO_TSK_NOT_SUSPENDED;
        OS_GOTO_ERREND();
    }

⑶  taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
⑸      OsSchedTaskEnQueue(taskCB);
        if (g_taskScheduled) {
            LOS_IntRestore(intSave);
⑹          LOS_Schedule();
            return LOS_OK;
        }
    }

    LOS_IntRestore(intSave);
    return LOS_OK;

LOS_ERREND:
    LOS_IntRestore(intSave);
    return retErr;
}

3.2.2 挂起指定的任务LOS_TaskSuspend()

函数用于挂起指定的任务。⑴处获取任务的TCB,⑵处开始获取任务的状态进行判断,如果任务没有创建、任务已经挂起,返回相应的错误码。⑶处如果任务是运行状态,并且锁任务调度时,跳转到LOS_ERREND结束挂起操作。⑷处如果任务是就绪状态,调用函数从就绪队列出队,并取消任务的就绪状态。⑸处语句设置任务状态为阻塞状态。⑹如果挂起的是当前运行的任务,则会主动触发调度。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;
    UINT32 retErr;

    retErr = OsCheckTaskIDValid(taskID);
    if (retErr != LOS_OK) {
        return retErr;
    }

⑴  taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
⑵  tempStatus = taskCB->taskStatus;
    if (tempStatus & OS_TASK_STATUS_UNUSED) {
        retErr = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    }

    if (tempStatus & OS_TASK_STATUS_SUSPEND) {
        retErr = LOS_ERRNO_TSK_ALREADY_SUSPENDED;
        OS_GOTO_ERREND();
    }if ((tempStatus & OS_TASK_STATUS_RUNNING) && (g_losTaskLock != 0)) {
        retErr = LOS_ERRNO_TSK_SUSPEND_LOCKED;
        OS_GOTO_ERREND();
    }if (tempStatus & OS_TASK_STATUS_READY) {
        OsSchedTaskDeQueue(taskCB);
    }

⑸  taskCB->taskStatus |= OS_TASK_STATUS_SUSPEND;
    OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTOSUSPENDEDLIST, taskCB);if (taskID == g_losTask.runTask->taskID) {
        LOS_IntRestore(intSave);
        LOS_Schedule();
        return LOS_OK;
    }

    LOS_IntRestore(intSave);
    return LOS_OK;

LOS_ERREND:
    LOS_IntRestore(intSave);
    return retErr;
}

3.2.3 任务延时等待LOS_TaskDelay()

任务延时等待,释放CPU,等待时间到期后该任务会重新进入就绪状态。⑴处代码判断系统处于中断,如果是,则返回错误码,不允许任务延时等待。⑵如果处于锁任务调度期间,则返回错误码。

⑶处如果延迟的时间为0,则执行让权操作,否则执行⑷,调用函数OsSchedDelay()把当前任务设置为延时等待状态,然后调用LOS_Schedule()触发调度。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
{
    UINTPTR intSave;if (OS_INT_ACTIVE) {
        return LOS_ERRNO_TSK_DELAY_IN_INT;
    }if (g_losTaskLock != 0) {
        return LOS_ERRNO_TSK_DELAY_IN_LOCK;
    }

    OsHookCall(LOS_HOOK_TYPE_TASK_DELAY, tick);if (tick == 0) {
        return LOS_TaskYield();
    } else {
        intSave = LOS_IntLock();
⑷      OsSchedDelay(g_losTask.runTask, tick);
        OsHookCall(LOS_HOOK_TYPE_MOVEDTASKTODELAYEDLIST, g_losTask.runTask);
        LOS_IntRestore(intSave);
        LOS_Schedule();
    }

    return LOS_OK;
}

另外还提供了函数LOS_Msleep()LOS_UDelay(),前者以毫秒为单位进行延迟等待。后者也是以毫秒为单位进行延迟等待,但是不会触发任务调度,当前任务不会释放CPU

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR VOID LOS_Msleep(UINT32 mSecs)
{
    UINT32 interval;

    if (OS_INT_ACTIVE) {
        return;
    }

    if (mSecs == 0) {
        interval = 0;
    } else {
        interval = LOS_MS2Tick(mSecs);
        if (interval == 0) {
            interval = 1;
        }
    }

    (VOID)LOS_TaskDelay(interval);
}

VOID LOS_UDelay(UINT64 microseconds)
{
    UINT64 endTime;

    if (microseconds == 0) {
        return;
    }

    endTime = (microseconds / OS_SYS_US_PER_SECOND) * OS_SYS_CLOCK +
            (microseconds % OS_SYS_US_PER_SECOND) * OS_SYS_CLOCK / OS_SYS_US_PER_SECOND;
    endTime = LOS_SysCycleGet() + endTime;
    while (LOS_SysCycleGet() < endTime) {
    }

    return;
}
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
代码语言:erlang
AI代码解释
复制
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.OpenHarmonyUboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

3.2.4 任务让权LOS_TaskYield()

让权函数通过把当前任务时间片设置为0,释放CPU占用,重新调度给其他高优先级任务执行。⑴处调用函数把当前任务时间片设置为0,然后执行⑵主动触发任务调度。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();
⑴  OsSchedYield();
    LOS_IntRestore(intSave);
⑵  LOS_Schedule();
    return LOS_OK;
}

接下来看下函数OsSchedYield()的源码。代码很简单,获取当前运行的任务,然后把其时间片设置为0,如下:

代码语言:shell
AI代码解释
复制
VOID OsSchedYield(VOID)
{
    LosTaskCB *runTask = g_losTask.runTask;

    runTask->timeSlice = 0;
}

3.3 控制任务调度

3.3.1 锁任务调度LOS_TaskLock()

锁任务调度LOS_TaskLock()比较简单,把任务锁调度计数器全局变量增加1即可,代码如下。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();
    g_losTaskLock++;
    LOS_IntRestore(intSave);
}

3.3.2 解锁任务调度LOS_TaskUnlock()

我们看看解锁任务调度函数LOS_TaskUnlock(),⑴处如果任务锁调度计数器全局变量数值大于0,对其减1。⑵处如果任务锁调度计数器等于0,则执行⑶处触发调度。代码如下:

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();if (g_losTaskLock > 0) {
        g_losTaskLock--;if (g_losTaskLock == 0) {
            LOS_IntRestore(intSave);
⑶          LOS_Schedule();
            return;
        }
    }

    LOS_IntRestore(intSave);
}

3.4 控制任务优先级

LiteOS-M内核支持动态设置任务的优先级,提供了一些操作。

3.4.1 设置指定任务的优先级LOS_TaskPriSet

支持设置指定任务Id的优先级,也支持对当前运行任务进行优先级设置。⑴处开始,做些基础校验,包含检验传入的优先级参数taskPrio,指定任务的Id,任务是否未创建等,如果没有通过参数校验,则返回错误码。⑵处调用函数设置任务优先级,稍后分析该函数。如果任务处于就绪状态或者运行状态,则会执行⑶主动触发任务调度。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
{
    BOOL isReady = FALSE;
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }

    if (taskID == g_idleTaskID) {
        return LOS_ERRNO_TSK_OPERATE_IDLE;
    }

    if (taskID == g_swtmrTaskID) {
        return LOS_ERRNO_TSK_OPERATE_SWTMR;
    }

    if (OS_CHECK_TSK_PID_NOIDLE(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
    tempStatus = taskCB->taskStatus;
    if (tempStatus & OS_TASK_STATUS_UNUSED) {
        LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

⑵  isReady = OsSchedModifyTaskSchedParam(taskCB, taskPrio);
    LOS_IntRestore(intSave);
    if (isReady) {
⑶      LOS_Schedule();
    }

    return LOS_OK;
}

接下来,我们分析下函数OsSchedModifyTaskSchedParam()。⑴处如果任务处于就绪状态,需要先出队设置优先级,然后入队就绪队列。如果非就绪状态,可以直接执行⑵处语句修改任务优先级。如果任务正在运行,需要返回TRUE,标记下需要任务调度。

代码语言:shell
AI代码解释
复制
BOOL OsSchedModifyTaskSchedParam(LosTaskCB *taskCB, UINT16 priority)
{
    if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
⑴      OsSchedTaskDeQueue(taskCB);
        taskCB->priority = priority;
        OsSchedTaskEnQueue(taskCB);
        return TRUE;
    }

⑵  taskCB->priority = priority;
    OsHookCall(LOS_HOOK_TYPE_TASK_PRIMODIFY, taskCB, taskCB->priority);
    if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
        return TRUE;
    }

    return FALSE;
}

3.4.2 获取指定任务的优先级LOS_TaskPriGet

获取指定任务的优先级LOS_TaskPriGet()代码比较简单,⑴处如果任务编号无效,返回错误码。⑵处如果任务未创建返回错误码。如果参数校验通过,执行⑶获取任务的优先级数值。

代码语言:shell
AI代码解释
复制
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 priority;if (OS_CHECK_TSK_PID_NOIDLE(taskID)) {
        return (UINT16)OS_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);

    intSave = LOS_IntLock();if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
        LOS_IntRestore(intSave);
        return (UINT16)OS_INVALID;
    }

⑶  priority = taskCB->priority;
    LOS_IntRestore(intSave);
    return priority;
}

3.5 任务阻塞和唤醒

最后,我们分析下函数OsSchedTaskWait()OsSchedTaskWake(),这2个函数定义在文件kernel\src\los_sched.c中。任务在申请互斥锁、信号量、出入队列、读写事件时,都可能导致任务进入阻塞状态,对应地也需要任务唤醒重新进入就绪队列状态。这2个函数就负责任务的阻塞和唤醒,我们分析下他们的代码。

3.5.1 任务阻塞

我们分析下任务阻塞的函数OsSchedTaskWait(),需要2个参数:LOS_DL_LIST *list是互斥锁等资源的阻塞链表,阻塞的任务会挂这个链表里;UINT32 ticks是任务阻塞的时间。分析下具体代码:

⑴获取正在请求互斥锁等资源的当前任务,⑵设置任务状态为阻塞状态。⑶把任务插入互斥锁等资源的阻塞链表的尾部。⑷如果不是永久阻塞等待,任务的状态还需要设置为OS_TASK_STATUS_PEND_TIME,然后设置任务的等待时间为传入的参数。

代码语言:shell
AI代码解释
复制
VOID OsSchedTaskWait(LOS_DL_LIST *list, UINT32 ticks)
{
⑴  LosTaskCB *runTask = g_losTask.runTask;

⑵  runTask->taskStatus |= OS_TASK_STATUS_PEND;
⑶  LOS_ListTailInsert(list, &runTask->pendList);

    if (ticks != LOS_WAIT_FOREVER) {
⑷      runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;
        runTask->waitTimes = ticks;
    }
}

3.5.2 任务唤醒

我们分析下任务唤醒的函数OsSchedTaskWake(),需要1个参数:LosTaskCB *resumedTask是需要唤醒的任务;任务唤醒函数会从阻塞链表里删除并加入就绪队列,下面分析下具体代码:

⑴把要唤醒的任务从所在的阻塞队列中删除,然后更改状态不再为阻塞状态。⑵如果任务不是永久等待,需要从定时器排序链表中删除,并设置状态不再是等待超时。⑶如果任务是阻塞状态,改为就绪状态并加入就绪队列。

代码语言:shell
AI代码解释
复制
VOID OsSchedTaskWake(LosTaskCB *resumedTask)
{
⑴  LOS_ListDelete(&resumedTask->pendList);
    resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND;if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
        OsDeleteSortLink(&resumedTask->sortList, OS_SORT_LINK_TASK);
        resumedTask->taskStatus &= ~OS_TASK_STATUS_PEND_TIME;
    }if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPEND)) {
        OsSchedTaskEnQueue(resumedTask);
    }
}

小结

本文带领大家一起剖析了鸿蒙轻内核任务模块的源代码,包含任务模块的结构体,任务初始化过程源代码,任务常用操作的源代码。

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
OpenHarmony 轻内核M核源码分析系列十一(1) 信号量Semaphore
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数。以同步为目的的信号量和以互斥为目的的信号量在使用上存在差异。本文通过分析鸿蒙轻内核信号量模块的源码,掌握信号量使用上的差异。
小帅聊鸿蒙
2025/05/23
440
OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(3)任务调度模块
调度,Schedule也称为Dispatch,是操作系统的一个重要模块,它负责选择系统要处理的下一个任务。调度模块需要协调处于就绪状态的任务对资源的竞争,按优先级策略从就绪队列中获取高优先级的任务,给予资源使用权。
小帅聊鸿蒙
2025/05/22
1020
OpenHarmony 轻内核M核源码分析系列十五 CPU使用率CPUP
CPUP(Central Processing Unit Percentage,CPU占用率)分为系统CPU占用率和任务CPU占用率。用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。通过系统中各个任务的CPU占用情况,判断各个任务的CPU占用率是否符合设计的预期。
小帅聊鸿蒙
2025/05/26
620
OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(1)任务栈
继续分析鸿蒙轻内核源码,我们本文开始要分析下任务及任务调度模块。首先,我们介绍下任务栈的基础概念。任务栈是高地址向低地址生长的递减栈,栈指针指向即将入栈的元素位置。初始化后未使用过的栈空间初始化的内容为宏OS_TASK_STACK_INIT代表的数值0xCACACACA,栈顶初始化为宏OS_TASK_MAGIC_WORD代表的数值0xCCCCCCCC。一个任务栈的示意图如下,其中,栈底指针是栈的最大的内存地址,栈顶指针,是栈的最小的内存地址,栈指针从栈底向栈顶方向生长。
小帅聊鸿蒙
2025/05/21
480
OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(1)任务栈
OpenHarmony 轻内核M核源码分析系列十七(1) 异常钩子函数类型
本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例。鸿蒙轻内核异常钩子模块代码主要在components\exchook目录下。
小帅聊鸿蒙
2025/05/27
760
OpenHarmony 轻内核M核源码分析系列十三 消息队列Queue
队列(Queue)是一种常用于任务间通信的数据结构。任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。如果将读队列和写队列的超时时间设置为0,则不会挂起任务,接口会直接返回,这就是非阻塞模式。消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用。
小帅聊鸿蒙
2025/05/26
850
鸿蒙轻内核M核源码分析系列十三(续) 消息队列QueueMail接口
之前分析过队列(Queue)的源代码,了解了队列初始化、队列创建、删除、队列读取写入等操作。队列还提供了两个接口OsQueueMailAlloc和OsQueueMailFree。队列可以和一个静态内存池关联起来,一个任务从静态内存池申请内存块时,如果申请不到,会把该任务插入到队列的内存阻塞链表中,等有其他任务释放内存时,该任务会被分配内存块。
玖柒的小窝
2021/09/17
2850
OpenHarmony 轻内核M核源码分析系列九 互斥锁Mutex
多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用。鸿蒙轻内核使用互斥锁来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占式处理。另外,互斥锁可以解决信号量存在的优先级翻转问题。用互斥锁处理临界资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个临界资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个临界资源,保证了临界资源操作的完整性。
小帅聊鸿蒙
2025/05/23
800
OpenHarmony 轻内核M核源码分析系列三 数据结构-任务排序链表
在鸿蒙轻内核源码分析系列一和系列二,我们分析了双向循环链表、优先级就绪队列的源码。本文会继续给读者介绍鸿蒙轻内核源码中重要的数据结构:任务排序链表TaskSortLinkAttr。鸿蒙轻内核的任务排序链表,用于任务延迟到期/超时唤醒等业务场景,是一个非常重要、非常基础的数据结构。本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例。
小帅聊鸿蒙
2025/05/20
860
OpenHarmony 轻内核M核源码分析系列三 数据结构-任务排序链表
OpenHarmony 内核源码分析(Fork篇) | 一次调用,两次返回
笔者第一次看到fork时,说是一次调用,两次返回,当时就懵圈了,多新鲜,真的很难理解.因为这足以颠覆了以往对函数的认知, 函数调用还能这么玩,父进程调用一次,父子进程各返回一次.而且只能通过返回值来判断是哪个进程的返回.所以一直有几个问题缠绕在脑海中.
小帅聊鸿蒙
2025/03/20
1050
OpenHarmony 内核源码分析(Fork篇) | 一次调用,两次返回
OpenHarmony实战—内核对象事件之源码详解
对于嵌入式开发工作人员和技术爱好者来说,深入了解常见任务间 IPC,有助于学习和研发内核。本文将从数据结构和算法解析 OpenHarmony 的事件机制,带大家深入了解内核任务间 IPC 原理。
小帅聊鸿蒙
2025/04/12
770
OpenHarmony实战—内核对象事件之源码详解
OpenHarmony 轻内核M核源码分析系列十 软件定时器Swtmr
软件定时器(Software Timer)是基于系统Tick时钟中断且由软件来模拟的定时器。当经过设定的Tick数后,会触发用户自定义的回调函数。硬件定时器受硬件的限制,数量上不足以满足用户的实际需求。鸿蒙轻内核提供了软件定时器功能可以提供更多的定时器,满足用户需求。
小帅聊鸿蒙
2025/05/23
690
OpenHarmony内核源码分析(时钟任务篇)
时钟节拍由配置为中断触发模式的硬件定时器产生,当中断到来时,将调用一次:void OsTickHandler(void),通知操作系统已经过去一个系统时钟;不同硬件定时器中断实现都不同,
小帅聊鸿蒙
2025/03/06
1440
OpenHarmony 内核源码分析(内核态锁篇) | 如何实现快锁Futex(下)
本篇为快锁下篇,说清楚快锁在内核态的实现,解答以下问题,它们在上篇的末尾被提出来。
小帅聊鸿蒙
2025/04/02
790
OpenHarmony 内核源码分析(内核态锁篇) | 如何实现快锁Futex(下)
OpenHarmony内核源码分析(事件控制篇) | 任务间多对多的同步方案
多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。
小帅聊鸿蒙
2025/03/14
830
OpenHarmony内核源码分析(事件控制篇) | 任务间多对多的同步方案
OpenHarmony 轻内核A核源码分析系列七 进程管理 (2)
本文先熟悉下进程管理的文件kernel\base\core\los_process.c中的内部接口,读读代码,做些记录。
小帅聊鸿蒙
2025/06/06
640
OpenHarmony 轻内核M核源码分析系列十七(2) 异常钩子函数的注册操作
本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例 。鸿蒙轻内核异常钩子模块代码主要在components\exchook目录下。异常钩子函数的注册、解注册、异常钩子类型定义在utils\los_debug.h|.c。
小帅聊鸿蒙
2025/05/27
640
OpenHarmony 轻内核M核源码分析系列十七(2) 异常钩子函数的注册操作
OpenHarmony 轻内核M核源码分析系列八 静态内存MemoryBox
内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。
小帅聊鸿蒙
2025/05/22
1000
OpenHarmony 轻内核M核源码分析系列八 静态内存MemoryBox
OpenHarmony内核源码分析(任务调度篇) | 任务是内核调度的单元
从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。
小帅聊鸿蒙
2025/03/07
1220
OpenHarmony 轻内核M核源码分析系列十七(3) 异常信息ExcInfo
本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例。鸿蒙轻内核异常钩子模块代码主要在components\exchook目录下。
小帅聊鸿蒙
2025/05/28
410
OpenHarmony 轻内核M核源码分析系列十七(3) 异常信息ExcInfo
推荐阅读
OpenHarmony 轻内核M核源码分析系列十一(1) 信号量Semaphore
440
OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(3)任务调度模块
1020
OpenHarmony 轻内核M核源码分析系列十五 CPU使用率CPUP
620
OpenHarmony 轻内核M核源码分析系列六 任务及任务调度(1)任务栈
480
OpenHarmony 轻内核M核源码分析系列十七(1) 异常钩子函数类型
760
OpenHarmony 轻内核M核源码分析系列十三 消息队列Queue
850
鸿蒙轻内核M核源码分析系列十三(续) 消息队列QueueMail接口
2850
OpenHarmony 轻内核M核源码分析系列九 互斥锁Mutex
800
OpenHarmony 轻内核M核源码分析系列三 数据结构-任务排序链表
860
OpenHarmony 内核源码分析(Fork篇) | 一次调用,两次返回
1050
OpenHarmony实战—内核对象事件之源码详解
770
OpenHarmony 轻内核M核源码分析系列十 软件定时器Swtmr
690
OpenHarmony内核源码分析(时钟任务篇)
1440
OpenHarmony 内核源码分析(内核态锁篇) | 如何实现快锁Futex(下)
790
OpenHarmony内核源码分析(事件控制篇) | 任务间多对多的同步方案
830
OpenHarmony 轻内核A核源码分析系列七 进程管理 (2)
640
OpenHarmony 轻内核M核源码分析系列十七(2) 异常钩子函数的注册操作
640
OpenHarmony 轻内核M核源码分析系列八 静态内存MemoryBox
1000
OpenHarmony内核源码分析(任务调度篇) | 任务是内核调度的单元
1220
OpenHarmony 轻内核M核源码分析系列十七(3) 异常信息ExcInfo
410
相关推荐
OpenHarmony 轻内核M核源码分析系列十一(1) 信号量Semaphore
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档