目錄:
繼續分析鴻蒙輕內核源碼,我們本文開始要分析下任務及任務調度模塊。首先,我們介紹下任務棧的基礎概念。任務棧是高地址向低地址生長的遞減棧,棧指針指向即將入棧的元素位置。初始化后未使用過的棧空間初始化的內容為宏OS_TASK_STACK_INIT
代表的數值0xCACACACA
,棧頂初始化為宏OS_TASK_MAGIC_WORD
代表的數值0xCCCCCCCC
。一個任務棧的示意圖如下,其中,棧底指針是棧的最大的內存地址,棧頂指針,是棧的最小的內存地址,棧指針從棧底向棧頂方向生長。
任務上下文(Task Context)是任務及任務調度模塊的另外一個重要的概念,它指的是任務運行的環境,例如包括程序計數器、堆棧指針、通用寄存器等內容。在多任務調度中,任務上下文切換(Task Context Switching)屬於核心內容,是多個任務運行在同一CPU
核上的基礎。在任務調度時,保存退出運行狀態的任務使用的寄存器信息到任務棧,還會從進入運行狀態的任務的棧中讀取上下文信息,恢復寄存器信息。
下面,我們剖析下任務棧、任務棧初始化的源代碼,若涉及開發板部分,以開發板工程targets\cortex-m7_nucleo_f767zi_gcc\
為例進行源碼分析。首先,看下任務上下文結構體。
1、 TaskContext上下文結構體定義
在文件kernel\arch\arm\cortex-m7\gcc\los_arch_context.h
中,定義的上下文的結構體如下,主要是浮點寄存器,通用寄存器。
2、 任務棧相關函數
2.1 任務棧初始化函數
在文件kernel\arch\arm\cortex-m7\gcc\los_context.c
中定義了任務棧初始化函數VOID *HalTskStackInit(t()
。該函數被文件kernel\src\los_task.c
中的函數UINT32 OsNewTaskInit()
調用完成任務初始化,並進一步在創建任務函數UINT32 LOS_TaskCreateOnly()
中調用,完成新創建任務的任務棧初始化。
該函數使用3個參數,一個是任務編號UINT32 taskID
,一個是初始化的棧的大小UINT32 stackSize
,第3個參數是棧頂指針VOID *topStack
。⑴處代碼把棧內容初始化為OS_TASK_STACK_INIT
,⑵處把棧頂初始化為OS_TASK_MAGIC_WORD
。
⑶處代碼獲取任務上下文的指針地址TaskContext *context
。對於新創建任務,從棧的底部開始,大小為sizeof(TaskContext)
的棧空間存放上下文的數據。⑷處如果支持浮點數計算,需要初始化浮點數相關的寄存器。⑸初始化通用寄存器,其中.uwLR
初始化為(UINT32)(UINTPTR)HalSysExit
。.uwPC
初始化為(UINT32)(UINTPTR)OsTaskEntry
,這是CPU
首次執行該任務時運行的第一條指令的位置。這2個函數下文會分析。
⑹處返回值是指針(VOID *)taskContext
,這個就是任務初始化后的棧指針,注意不是從棧底開始了,棧底保存的是上下文,棧指針要減去上下文占用的棧大小。在棧中,從TaskContext *context
指針增加的方向,依次保存上下文結構體的第一個成員,第二個成員…另外,初始化棧的時候,除了特殊的幾個寄存器,不同寄存器的初始值雖然沒有什么意義,也有些初始化的規律。比如R2
寄存器初始化為0x02020202L
,R12
寄存器初始化為0x12121212L
初始化的內容和寄存器編號有關聯,其余類似。