91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

鴻蒙內(nèi)核源碼Task/線程技術(shù)分析

鴻蒙系統(tǒng)HarmonyOS ? 來(lái)源:oschina ? 作者:鴻蒙源碼分析系列 ? 2020-10-18 10:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

鴻蒙內(nèi)核中,廣義上可理解為一個(gè)Task就是一個(gè)線程

一、怎么理解Task

1. 官方文檔是怎么描述線程

基本概念
從系統(tǒng)的角度看,線程是競(jìng)爭(zhēng)系統(tǒng)資源的最小運(yùn)行單元。線程可以使用或等待CPU、使用內(nèi)存空間等系統(tǒng)資源,并獨(dú)立于其它線程運(yùn)行。

鴻蒙內(nèi)核每個(gè)進(jìn)程內(nèi)的線程獨(dú)立運(yùn)行、獨(dú)立調(diào)度,當(dāng)前進(jìn)程內(nèi)線程的調(diào)度不受其它進(jìn)程內(nèi)線程的影響。

鴻蒙內(nèi)核中的線程采用搶占式調(diào)度機(jī)制,同時(shí)支持時(shí)間片輪轉(zhuǎn)調(diào)度和FIFO調(diào)度方式。

鴻蒙內(nèi)核的線程一共有32個(gè)優(yōu)先級(jí)(0-31),最高優(yōu)先級(jí)為0,最低優(yōu)先級(jí)為31。

當(dāng)前進(jìn)程內(nèi)高優(yōu)先級(jí)的線程可搶占當(dāng)前進(jìn)程內(nèi)低優(yōu)先級(jí)線程,當(dāng)前進(jìn)程內(nèi)低優(yōu)先級(jí)線程必須在當(dāng)前進(jìn)程內(nèi)高優(yōu)先級(jí)線程阻塞或結(jié)束后才能得到調(diào)度。

線程狀態(tài)說(shuō)明:

初始化(Init):該線程正在被創(chuàng)建。

就緒(Ready):該線程在就緒列表中,等待CPU調(diào)度。

運(yùn)行(Running):該線程正在運(yùn)行。

阻塞(Blocked):該線程被阻塞掛起。Blocked狀態(tài)包括:pend(因?yàn)殒i、事件、信號(hào)量等阻塞)、suspend(主動(dòng)pend)、delay(延時(shí)阻塞)、pendtime(因?yàn)殒i、事件、信號(hào)量時(shí)間等超時(shí)等待)。

退出(Exit):該線程運(yùn)行結(jié)束,等待父線程回收其控制塊資源。

圖 1 線程狀態(tài)遷移示意圖

注意官方文檔說(shuō)的是線程,沒(méi)有提到task(任務(wù)),但內(nèi)核源碼中卻有大量 task代碼,很少有線程(thread)代碼 ,這是怎么回事?
其實(shí)在鴻蒙內(nèi)核中, task就是線程, 初學(xué)者完全可以這么理解,但二者還是有區(qū)別,否則干嘛要分兩個(gè)詞描述。
到底有什么區(qū)別?是管理上的區(qū)別,task是調(diào)度層面的概念,線程是進(jìn)程層面的概念。 就像同一個(gè)人在不同的管理體系中會(huì)有不同的身份一樣,一個(gè)男人既可以是 孩子,爸爸,丈夫,或者程序員,視角不同功能也會(huì)不同。

如何證明是一個(gè)東西,繼續(xù)再往下看。

2. 執(zhí)行task命令

鴻蒙 task 命令的執(zhí)行結(jié)果:

task命令 查出每個(gè)任務(wù)在生命周期內(nèi)的運(yùn)行情況,它運(yùn)行的內(nèi)存空間,優(yōu)先級(jí),時(shí)間片,入口執(zhí)行函數(shù),進(jìn)程ID,狀態(tài)等等信息,非常的復(fù)雜。這么復(fù)雜的信息就需要一個(gè)結(jié)構(gòu)體來(lái)承載。而這個(gè)結(jié)構(gòu)體就是 LosTaskCB(任務(wù)控制塊)

對(duì)應(yīng)張大爺?shù)墓适拢簍ask就是一個(gè)用戶的節(jié)目清單里的一個(gè)節(jié)目,用戶總清單就是一個(gè)進(jìn)程,所以上面會(huì)有很多的節(jié)目。

3. task長(zhǎng)得什么樣子?

說(shuō)LosTaskCB之前先說(shuō)下官方文檔任務(wù)狀態(tài)對(duì)應(yīng)的 define,可以看出task和線程是一個(gè)東西。

#define OS_TASK_STATUS_INIT         0x0001U
#define OS_TASK_STATUS_READY        0x0002U
#define OS_TASK_STATUS_RUNNING      0x0004U
#define OS_TASK_STATUS_SUSPEND      0x0008U
#define OS_TASK_STATUS_PEND         0x0010U
#define OS_TASK_STATUS_DELAY        0x0020U
#define OS_TASK_STATUS_TIMEOUT      0x0040U
#define OS_TASK_STATUS_PEND_TIME    0x0080U
#define OS_TASK_STATUS_EXIT         0x0100U

LosTaskCB長(zhǎng)什么樣?抱歉,它確實(shí)有點(diǎn)長(zhǎng),但還是要全部貼出全貌。

typedef struct {
    VOID            *stackPointer;      /**< Task stack pointer */
    UINT16          taskStatus;         /**< Task status */
    UINT16          priority;           /**< Task priority */
    UINT16          policy;
    UINT16          timeSlice;          /**< Remaining time slice */
    UINT32          stackSize;          /**< Task stack size */
    UINTPTR         topOfStack;         /**< Task stack top */
    UINT32          taskID;             /**< Task ID */
    TSK_ENTRY_FUNC  taskEntry;          /**< Task entrance function */
    VOID            *joinRetval;        /**< pthread adaption */
    VOID            *taskSem;           /**< Task-held semaphore */
    VOID            *taskMux;           /**< Task-held mutex */
    VOID            *taskEvent;         /**< Task-held event */
    UINTPTR         args[4];            /**< Parameter, of which the maximum number is 4 */
    CHAR            taskName[OS_TCB_NAME_LEN]; /**< Task name */
    LOS_DL_LIST     pendList;           /**< Task pend node */
    LOS_DL_LIST     threadList;         /**< thread list */
    SortLinkList    sortList;           /**< Task sortlink node */
    UINT32          eventMask;          /**< Event mask */
    UINT32          eventMode;          /**< Event mode */
    UINT32          priBitMap;          /**< BitMap for recording the change of task priority,
                                             the priority can not be greater than 31 */
    INT32           errorNo;            /**< Error Num */
    UINT32          signal;             /**< Task signal */
    sig_cb          sig;
#if (LOSCFG_KERNEL_SMP == YES)
    UINT16          currCpu;            /**< CPU core number of this task is running on */
    UINT16          lastCpu;            /**< CPU core number of this task is running on last time */
    UINT16          cpuAffiMask;        /**< CPU affinity mask, support up to 16 cores */
    UINT32          timerCpu;           /**< CPU core number of this task is delayed or pended */
#if (LOSCFG_KERNEL_SMP_TASK_SYNC == YES)
    UINT32          syncSignal;         /**< Synchronization for signal handling */
#endif
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES)
    LockDep         lockDep;
#endif
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
    SchedStat       schedStat;          /**< Schedule statistics */
#endif
#endif
    UINTPTR         userArea;
    UINTPTR         userMapBase;
    UINT32          userMapSize;        /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE */
    UINT32          processID;          /**< Which belong process */
    FutexNode       futex;
    LOS_DL_LIST     joinList;           /**< join list */
    LOS_DL_LIST     lockList;           /**< Hold the lock list */
    UINT32          waitID;             /**< Wait for the PID or GID of the child process */
    UINT16          waitFlag;           /**< The type of child process that is waiting, belonging to a group or parent,
                                             a specific child process, or any child process */
#if (LOSCFG_KERNEL_LITEIPC == YES)
    UINT32          ipcStatus;
    LOS_DL_LIST     msgListHead;
    BOOL            accessMap[LOSCFG_BASE_CORE_TSK_LIMIT];
#endif
} LosTaskCB;

結(jié)構(gòu)體LosTaskCB內(nèi)容很多,各代表什么含義?

LosTaskCB相當(dāng)于任務(wù)在內(nèi)核中的身份證,它反映出每個(gè)任務(wù)在生命周期內(nèi)的運(yùn)行情況。既然是周期就會(huì)有狀態(tài),要運(yùn)行就需要內(nèi)存空間,就需要被內(nèi)核算法調(diào)度,被選中CPU就去執(zhí)行代碼段指令,CPU要執(zhí)行就需要告訴它從哪里開(kāi)始執(zhí)行,因?yàn)槭嵌嗑€程,但只有一個(gè)CPU就需要不斷的切換任務(wù),那執(zhí)行會(huì)被中斷,也需要再恢復(fù)后繼續(xù)執(zhí)行,又如何保證恢復(fù)的任務(wù)執(zhí)行不會(huì)出錯(cuò),這些問(wèn)題都需要說(shuō)明白。

二、Task怎么管理

1.什么是任務(wù)池?

前面已經(jīng)說(shuō)了任務(wù)是內(nèi)核調(diào)度層面的概念,調(diào)度算法保證了task有序的執(zhí)行,調(diào)度機(jī)制詳見(jiàn)其他姊妹篇的介紹。
如此多的任務(wù)怎么管理和執(zhí)行?管理靠任務(wù)池和就緒隊(duì)列,執(zhí)行靠調(diào)度算法。
代碼如下(OsTaskInit):

LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID)
{
   
    UINT32 index;
    UINT32 ret;
    UINT32 size;

    g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;//任務(wù)池中最多默認(rèn)128個(gè),可謂鐵打的任務(wù)池流水的線程
    size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
    /* * This memory is resident memory and is used to save the system resources * of task control block and will not be freed. */
    g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);//任務(wù)池 常駐內(nèi)存,不被釋放
    if (g_taskCBArray == NULL) {
   
        return LOS_ERRNO_TSK_NO_MEMORY;
    }
    (VOID)memset_s(g_taskCBArray, size, 0, size);

    LOS_ListInit(&g_losFreeTask);//空閑任務(wù)鏈表
    LOS_ListInit(&g_taskRecyleList);//需回收任務(wù)鏈表
    for (index = 0; index < g_taskMaxNum; index++) {
   
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
        g_taskCBArray[index].taskID = index;//任務(wù)ID最大默認(rèn)127
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);//都插入空閑任務(wù)鏈表
    }

    ret = OsPriQueueInit();//創(chuàng)建32個(gè)任務(wù)優(yōu)先級(jí)隊(duì)列,即32個(gè)雙向循環(huán)鏈表
    if (ret != LOS_OK) {
   
        return LOS_ERRNO_TSK_NO_MEMORY;
    }

    /* init sortlink for each core */
    for (index = 0; index < LOSCFG_KERNEL_CORE_NUM; index++) {
   
        ret = OsSortLinkInit(&g_percpu[index].taskSortLink);//每個(gè)CPU內(nèi)核都有一個(gè)執(zhí)行任務(wù)鏈表
        if (ret != LOS_OK) {
   
            return LOS_ERRNO_TSK_NO_MEMORY;
        }
    }
    return LOS_OK;
}

g_taskCBArray 就是個(gè)任務(wù)池,默認(rèn)創(chuàng)建128個(gè)任務(wù),常駐內(nèi)存,不被釋放。

g_losFreeTask是空閑任務(wù)鏈表,想創(chuàng)建任務(wù)時(shí)來(lái)這里申請(qǐng)一個(gè)空閑任務(wù),用完了就回收掉,繼續(xù)給后面的申請(qǐng)使用。
g_taskRecyleList是回收任務(wù)鏈表,專用來(lái)回收exit 任務(wù),任務(wù)所占資源被確認(rèn)歸還后被徹底刪除,就像員工離職一樣,得有個(gè)離職隊(duì)列和流程,要?dú)w還電腦,郵箱,有沒(méi)有借錢要還的 等操作。

對(duì)應(yīng)張大爺?shù)墓适拢河脩粢獊?lái)場(chǎng)館領(lǐng)取表格填節(jié)目單,場(chǎng)館只準(zhǔn)備了128張表格,領(lǐng)完就沒(méi)有了,但是節(jié)目表演完了會(huì)回收表格,這樣多了一張表格就可以給其他人領(lǐng)取了,這128張表格對(duì)應(yīng)鴻蒙內(nèi)核這就是任務(wù)池,簡(jiǎn)單吧。

2.就緒隊(duì)列是怎么回事

CPU執(zhí)行速度是很快的,鴻蒙內(nèi)核默認(rèn)一個(gè)時(shí)間片是 10ms, 資源有限,需要在眾多任務(wù)中來(lái)回的切換,所以絕不能讓CPU等待任務(wù),CPU就像公司最大的領(lǐng)導(dǎo),下面很多的部門等領(lǐng)導(dǎo)來(lái)審批,吃飯。只有大家等領(lǐng)導(dǎo),哪有領(lǐng)導(dǎo)等你們的道理,所以工作要提前準(zhǔn)備好,每個(gè)部門的優(yōu)先級(jí)又不一樣,所以每個(gè)部門都要有個(gè)任務(wù)隊(duì)列,里面放的是領(lǐng)導(dǎo)能直接處理的任務(wù),沒(méi)準(zhǔn)備好的不要放進(jìn)來(lái),因?yàn)檫@是給CPU提前準(zhǔn)備好的糧食!
這就是就緒隊(duì)列的原理,一共有32個(gè)就緒隊(duì)列,進(jìn)程和線程都有,因?yàn)榫€程的優(yōu)先級(jí)是默認(rèn)32個(gè), 每個(gè)隊(duì)列中放同等優(yōu)先級(jí)的task.
還是看源碼吧

#define OS_PRIORITY_QUEUE_NUM 32
UINT32 OsPriQueueInit(VOID)
{
   
    UINT32 priority;

    /* system resident resource */
    g_priQueueList = (LOS_DL_LIST *)LOS_MemAlloc(m_aucSysMem0, (OS_PRIORITY_QUEUE_NUM * sizeof(LOS_DL_LIST)));//常駐內(nèi)存,不被釋放
    if (g_priQueueList == NULL) {
   
        return LOS_NOK;
    }

    for (priority = 0; priority < OS_PRIORITY_QUEUE_NUM; ++priority) {
   
        LOS_ListInit(&g_priQueueList[priority]);
    }
    return LOS_OK;
}

注意看g_priQueueList 的內(nèi)存分配,就是32個(gè)LOS_DL_LIST,還記得LOS_DL_LIST的妙用嗎,不清楚的去鴻蒙源碼分析(總目錄)里面翻。

對(duì)應(yīng)張大爺?shù)墓适拢壕褪情T口那些排隊(duì)的都是至少有一個(gè)節(jié)目單是符合表演標(biāo)準(zhǔn)的,資源都到位了,沒(méi)有的連排隊(duì)的資格都木有,就慢慢等吧。

3.任務(wù)棧是怎么回事

每個(gè)任務(wù)都是獨(dú)立開(kāi)的,任務(wù)之間也相互獨(dú)立,之間通訊通過(guò)IPC,這里的“獨(dú)立”指的是每個(gè)任務(wù)都有自己的運(yùn)行環(huán)境 —— ??臻g,稱為任務(wù)棧,??臻g里保存的信息包含局部變量、寄存器、函數(shù)參數(shù)、函數(shù)返回地址等等
但系統(tǒng)中只有一個(gè)CPU,任務(wù)又是獨(dú)立的,調(diào)度的本質(zhì)就是CPU執(zhí)行一個(gè)新task,老task在什么地方被中斷誰(shuí)也不清楚,是隨機(jī)的。那如何保證老任務(wù)被再次調(diào)度選中時(shí)還能從上次被中斷的地方繼續(xù)玩下去呢?

答案是:任務(wù)上下文,CPU內(nèi)有一堆的寄存器,CPU運(yùn)行本質(zhì)的就是這些寄存器的值不斷的變化,只要切換時(shí)把這些值保存起來(lái),再還原回去就能保證task的連續(xù)執(zhí)行,讓用戶毫無(wú)感知。鴻蒙內(nèi)核給一個(gè)任務(wù)執(zhí)行的時(shí)間是 20ms ,也就是說(shuō)有多任務(wù)競(jìng)爭(zhēng)的情況下,一秒鐘內(nèi)最多要來(lái)回切換50次。

對(duì)應(yīng)張大爺?shù)墓适拢壕褪桥龅焦?jié)目沒(méi)有表演完就必須打斷的情況下,需要把當(dāng)時(shí)的情況記錄下來(lái),比如小朋友在演躲貓貓的游戲,一半不演了,張三正在樹(shù)上,李四正在廁所躲,都記錄下來(lái),下次再回來(lái)你們上次在哪就會(huì)哪呆著去,就位了繼續(xù)表演。這樣就接上了,觀眾就木有感覺(jué)了。
任務(wù)上下文(TaskContext)是怎樣的呢?還是直接看源碼

/* The size of this structure must be smaller than or equal to the size specified by OS_TSK_STACK_ALIGN (16 bytes). */
typedef struct {
   
#if !defined(LOSCFG_ARCH_FPU_DISABLE)
    UINT64 D[FP_REGS_NUM]; /* D0-D31 */
    UINT32 regFPSCR;       /* FPSCR */
    UINT32 regFPEXC;       /* FPEXC */
#endif
    UINT32 resved;          /* It's stack 8 aligned */
    UINT32 regPSR;
    UINT32 R[GEN_REGS_NUM]; /* R0-R12 */
    UINT32 SP;              /* R13 */
    UINT32 LR;              /* R14 */
    UINT32 PC;              /* R15 */
} TaskContext;

發(fā)現(xiàn)基本都是CPU寄存器的恢復(fù)現(xiàn)場(chǎng)值, 具體各寄存器有什么作用大家可以去網(wǎng)上詳查,后續(xù)也有專門的文章來(lái)介紹。這里說(shuō)其中的三個(gè)寄存器 SP, LR, PC

LR
用途有二,一是保存子程序返回地址,當(dāng)調(diào)用BL、BX、BLX等跳轉(zhuǎn)指令時(shí)會(huì)自動(dòng)保存返回地址到LR;二是保存異常發(fā)生的異常返回地址。

PC(Program Counter)
為程序計(jì)數(shù)器,用于保存程序的執(zhí)行地址,在ARM的三級(jí)流水線架構(gòu)中,程序流水線包括取址、譯碼和執(zhí)行三個(gè)階段,PC指向的是當(dāng)前取址的程序地址,所以32位ARM中,譯碼地址(正在解析還未執(zhí)行的程序)為PC-4,執(zhí)行地址(當(dāng)前正在執(zhí)行的程序地址)為PC-8, 當(dāng)突然發(fā)生中斷的時(shí)候,保存的是PC的地址。

SP
每一種異常模式都有其自己獨(dú)立的r13,它通常指向異常模式所專用的堆棧,當(dāng)ARM進(jìn)入異常模式的時(shí)候,程序就可以把一般通用寄存器壓入堆棧,返回時(shí)再出棧,保證了各種模式下程序的狀態(tài)的完整性。

4.任務(wù)棧初始化

任務(wù)棧的初始化就是任務(wù)上下文的初始化,因?yàn)槿蝿?wù)沒(méi)開(kāi)始執(zhí)行,里面除了上下文不會(huì)有其他內(nèi)容,注意上下文存放的位置在棧的底部。

三、Task函數(shù)集

LITE_OS_SEC_TEXT_INIT VOID *OsTaskStackInit(UINT32 taskID, UINT32 stackSize, VOID *topStack, BOOL initFlag)
{
   
    UINT32 index = 1;
    TaskContext *taskContext = NULL;

    if (initFlag == TRUE) {
   
        OsStackInit(topStack, stackSize);
    }
    taskContext = (TaskContext *)(((UINTPTR)topStack + stackSize) - sizeof(TaskContext));//注意看上下文將存放在棧的底部

    /* initialize the task context */
#ifdef LOSCFG_GDB
    taskContext->PC = (UINTPTR)OsTaskEntrySetupLoopFrame;
#else
    taskContext->PC = (UINTPTR)OsTaskEntry;//程序計(jì)數(shù)器,CPU首次執(zhí)行task時(shí)跑的第一條指令位置
#endif
    taskContext->LR = (UINTPTR)OsTaskExit;  /* LR should be kept, to distinguish it's THUMB or ARM instruction */
    taskContext->resved = 0x0;
    taskContext->R[0] = taskID;             /* R0 */
    taskContext->R[index++] = 0x01010101;   /* R1, 0x01010101 : reg initialed magic word */
    for (; index < GEN_REGS_NUM; index++) {
   //R2 - R12的初始化很有意思,為什么要這么做?
        taskContext->R[index] = taskContext->R[index - 1] + taskContext->R[1]; /* R2 - R12 */
    }

#ifdef LOSCFG_INTERWORK_THUMB // 16位模式
    taskContext->regPSR = PSR_MODE_SVC_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMNB-mode) */
#else
    taskContext->regPSR = PSR_MODE_SVC_ARM;   /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */
#endif

#if !defined(LOSCFG_ARCH_FPU_DISABLE)
    /* 0xAAA0000000000000LL : float reg initialed magic word */
    for (index = 0; index < FP_REGS_NUM; index++) {
   
        taskContext->D[index] = 0xAAA0000000000000LL + index; /* D0 - D31 */
    }
    taskContext->regFPSCR = 0;
    taskContext->regFPEXC = FP_EN;
#endif

    return (VOID *)taskContext;
}

1.使用場(chǎng)景和功能

任務(wù)創(chuàng)建后,內(nèi)核可以執(zhí)行鎖任務(wù)調(diào)度,解鎖任務(wù)調(diào)度,掛起,恢復(fù),延時(shí)等操作,同時(shí)也可以設(shè)置任務(wù)優(yōu)先級(jí),獲取任務(wù)優(yōu)先級(jí)。任務(wù)結(jié)束的時(shí)候,則進(jìn)行當(dāng)前任務(wù)自刪除操作。
Huawei LiteOS 系統(tǒng)中的任務(wù)管理模塊為用戶提供下面幾種功能。

功能分類 接口 描述
任務(wù)的創(chuàng)建和刪除 LOS_TaskCreateOnly 創(chuàng)建任務(wù),并使該任務(wù)進(jìn)入suspend狀態(tài),并不調(diào)度。
LOS_TaskCreate 創(chuàng)建任務(wù),并使該任務(wù)進(jìn)入ready狀態(tài),并調(diào)度。
LOS_TaskDelete 刪除指定的任務(wù)。
任務(wù)狀態(tài)控制 LOS_TaskResume 恢復(fù)掛起的任務(wù)。
LOS_TaskSuspend 掛起指定的任務(wù)。
LOS_TaskDelay 任務(wù)延時(shí)等待。
LOS_TaskYield 顯式放權(quán),調(diào)整指定優(yōu)先級(jí)的任務(wù)調(diào)度順序。
任務(wù)調(diào)度的控制 LOS_TaskLock 鎖任務(wù)調(diào)度。
LOS_TaskUnlock 解鎖任務(wù)調(diào)度。
任務(wù)優(yōu)先級(jí)的控制 LOS_CurTaskPriSet 設(shè)置當(dāng)前任務(wù)的優(yōu)先級(jí)。
LOS_TaskPriSet 設(shè)置指定任務(wù)的優(yōu)先級(jí)。
LOS_TaskPriGet 獲取指定任務(wù)的優(yōu)先級(jí)。
任務(wù)信息獲取 LOS_CurTaskIDGet 獲取當(dāng)前任務(wù)的ID。
LOS_TaskInfoGet 設(shè)置指定任務(wù)的優(yōu)先級(jí)。
LOS_TaskPriGet 獲取指定任務(wù)的信息。
LOS_TaskStatusGet 獲取指定任務(wù)的狀態(tài)。
LOS_TaskNameGet 獲取指定任務(wù)的名稱。
LOS_TaskInfoMonitor 監(jiān)控所有任務(wù),獲取所有任務(wù)的信息。
LOS_NextTaskIDGet 獲取即將被調(diào)度的任務(wù)的ID。

2.創(chuàng)建任務(wù)的過(guò)程

創(chuàng)建任務(wù)之前先了解另一個(gè)結(jié)構(gòu)體 tagTskInitParam

typedef struct tagTskInitParam {
   
    TSK_ENTRY_FUNC  pfnTaskEntry;  /**< Task entrance function */
    UINT16          usTaskPrio;    /**< Task priority */
    UINT16          policy;        /**< Task policy */
    UINTPTR         auwArgs[4];    /**< Task parameters, of which the maximum number is four */
    UINT32          uwStackSize;   /**< Task stack size */
    CHAR            *pcName;       /**< Task name */
#if (LOSCFG_KERNEL_SMP == YES)
    UINT16          usCpuAffiMask; /**< Task cpu affinity mask */
#endif
    UINT32          uwResved;      /**< It is automatically deleted if set to LOS_TASK_STATUS_DETACHED. It is unable to be deleted if set to 0. */
    UINT16          consoleID;     /**< The console id of task belongs */
    UINT32          processID;
    UserTaskParam   userParam;
} TSK_INIT_PARAM_S;

這些初始化參數(shù)是外露的任務(wù)初始參數(shù),pfnTaskEntry對(duì)java來(lái)說(shuō)就是你new進(jìn)程的run(),需要上層使用者提供.

看個(gè)例子吧:shell中敲 ping 命令看下它創(chuàng)建的過(guò)程

u32_t osShellPing(int argc, const char **argv)
{
   
    int ret;
    u32_t i = 0;
    u32_t count = 0;
    int count_set = 0;
    u32_t interval = 1000; /* default ping interval */
    u32_t data_len = 48; /* default data length */
    ip4_addr_t dst_ipaddr;
    TSK_INIT_PARAM_S stPingTask;
    // ...省去一些中間代碼
    /* start one task if ping forever or ping count greater than 60 */
    if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) {
   
        if (ping_taskid > 0) {
   
            PRINTK("Ping task already running and only support one now
");
            return LOS_NOK;
        }
        stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd;//線程的執(zhí)行函數(shù)
        stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//0x4000 = 16K 
        stPingTask.pcName = "ping_task";
        stPingTask.usTaskPrio = 8; /* higher than shell 優(yōu)先級(jí)高于10,屬于內(nèi)核態(tài)線程*/ 
        stPingTask.uwResved = LOS_TASK_STATUS_DETACHED;
        stPingTask.auwArgs[0] = dst_ipaddr.addr; /* network order */
        stPingTask.auwArgs[1] = count;
        stPingTask.auwArgs[2] = interval;
        stPingTask.auwArgs[3] = data_len;
        ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask);
    }
	// ...
    return LOS_OK;
ping_error:
    lwip_ping_usage();
    return LOS_NOK;
}

發(fā)現(xiàn)ping的調(diào)度優(yōu)先級(jí)是8,比shell 還高,那shell的是多少?答案是:看源碼是 9

LITE_OS_SEC_TEXT_MINOR UINT32 ShellTaskInit(ShellCB *shellCB)
{
   
    CHAR *name = NULL;
    TSK_INIT_PARAM_S initParam = {
   0};
    if (shellCB->consoleID == CONSOLE_SERIAL) {
   
        name = SERIAL_SHELL_TASK_NAME;
    } else if (shellCB->consoleID == CONSOLE_TELNET) {
   
        name = TELNET_SHELL_TASK_NAME;
    } else {
   
        return LOS_NOK;
    }
    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ShellTask;
    initParam.usTaskPrio   = 9; /* 9:shell task priority */
    initParam.auwArgs[0]   = (UINTPTR)shellCB;
    initParam.uwStackSize  = 0x3000;
    initParam.pcName       = name;
    initParam.uwResved     = LOS_TASK_STATUS_DETACHED;
    (VOID)LOS_EventInit(&shellCB->shellEvent);
    return LOS_TaskCreate(&shellCB->shellTaskHandle, &initParam);
}
關(guān)于shell后續(xù)會(huì)詳細(xì)介紹,請(qǐng)持續(xù)關(guān)注。

前置條件了解清楚后,具體看任務(wù)是如何一步步創(chuàng)建的,如何和進(jìn)程綁定,加入調(diào)度就緒隊(duì)列,還是繼續(xù)看源碼

LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
    UINT32 ret;
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;

    if (initParam == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    if (OS_INT_ACTIVE) {
        return LOS_ERRNO_TSK_YIELD_IN_INT;
    }

    if (initParam->uwResved & OS_TASK_FLAG_IDLEFLAG) {
        initParam->processID = OsGetIdleProcessID();
    } else if (OsProcessIsUserMode(OsCurrProcessGet())) {
        initParam->processID = OsGetKernelInitProcessID();
    } else {
        initParam->processID = OsCurrProcessGet()->processID;
    }
    initParam->uwResved &= ~OS_TASK_FLAG_IDLEFLAG;
    initParam->uwResved &= ~OS_TASK_FLAG_PTHREAD_JOIN;
    if (initParam->uwResved & LOS_TASK_STATUS_DETACHED) {
        initParam->uwResved = OS_TASK_FLAG_DETACHED;
    }

    ret = LOS_TaskCreateOnly(taskID, initParam);
    if (ret != LOS_OK) {
        return ret;
    }
    taskCB = OS_TCB_FROM_TID(*taskID);

    SCHEDULER_LOCK(intSave);
    taskCB->taskStatus &= ~OS_TASK_STATUS_INIT;
    OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, 0);
    SCHEDULER_UNLOCK(intSave);

    /* in case created task not running on this core,
       schedule or not depends on other schedulers status. */
    LOS_MpSchedule(OS_MP_CPU_ALL);
    if (OS_SCHEDULER_ACTIVE) {
        LOS_Schedule();//*kyf 任務(wù)創(chuàng)建完了 申請(qǐng)調(diào)度
    }

    return LOS_OK;
}
對(duì)應(yīng)張大爺?shù)墓适拢壕褪枪?jié)目單要怎么填,按格式來(lái),從哪里開(kāi)始演,要多大的空間,王場(chǎng)館好協(xié)調(diào)好現(xiàn)場(chǎng)的環(huán)境。這里注意在同一個(gè)節(jié)目單只要節(jié)目沒(méi)演完,王場(chǎng)館申請(qǐng)場(chǎng)地的空間就不能給別人用,這個(gè)場(chǎng)地空間對(duì)應(yīng)的就是鴻蒙任務(wù)的棧空間,除非整個(gè)節(jié)目單都完了,就回收了。把整個(gè)場(chǎng)地干干凈凈的留給下一個(gè)人的節(jié)目單來(lái)表演。

至此的創(chuàng)建已經(jīng)完成,已各就各位,源碼最后還申請(qǐng)了一次LOS_Schedule();因?yàn)轼櫭傻恼{(diào)度方式是搶占式的,如何本次task的任務(wù)優(yōu)先級(jí)高于其他就緒隊(duì)列,那么接下來(lái)要執(zhí)行的任務(wù)就是它了!
編輯:hfy

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    4

    文章

    1468

    瀏覽量

    42888
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    509

    瀏覽量

    20829
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2642

    瀏覽量

    69871
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    代碼照亮未來(lái):蘭州大學(xué)開(kāi)源鴻蒙技術(shù)俱樂(lè)部的六種青春答卷

    ;沒(méi)有單打獨(dú)斗的英雄,只有并肩攻堅(jiān)的戰(zhàn)友。從內(nèi)核調(diào)試到應(yīng)用創(chuàng)新,從社區(qū)貢獻(xiàn)到生態(tài)布道,這群心懷“技術(shù)報(bào)國(guó)”理想的青年,正在用一行行代碼構(gòu)建開(kāi)源鴻蒙的明天。 這六位同學(xué),正是技術(shù)俱樂(lè)部百
    的頭像 發(fā)表于 01-19 16:58 ?539次閱讀
    代碼照亮未來(lái):蘭州大學(xué)開(kāi)源<b class='flag-5'>鴻蒙</b><b class='flag-5'>技術(shù)</b>俱樂(lè)部的六種青春答卷

    Linux多線程對(duì)比單線程的優(yōu)勢(shì)

    的示例代碼,創(chuàng)建三個(gè)線程,每個(gè)線程實(shí)現(xiàn)不同的任務(wù):#include #include void *task1(void *arg) { printf(\"Thread 1
    發(fā)表于 12-01 06:11

    開(kāi)源鴻蒙技術(shù)大會(huì)2025丨虛擬化與容器分論壇:構(gòu)筑開(kāi)源鴻蒙虛擬化技術(shù)高地

    隨著開(kāi)源鴻蒙技術(shù)的快速發(fā)展,各行各業(yè)、各品類的生態(tài)設(shè)備加速融入生態(tài),當(dāng)數(shù)字世界的邊界不斷拓寬,我們正站在操作系統(tǒng)革命的十字路口。虛擬化技術(shù)打破硬件桎梏,?讓一塊芯片承載多重宇宙,從智能手表到車載系統(tǒng)
    的頭像 發(fā)表于 11-20 17:35 ?914次閱讀
    開(kāi)源<b class='flag-5'>鴻蒙</b><b class='flag-5'>技術(shù)</b>大會(huì)2025丨虛擬化與容器分論壇:構(gòu)筑開(kāi)源<b class='flag-5'>鴻蒙</b>虛擬化<b class='flag-5'>技術(shù)</b>高地

    開(kāi)源鴻蒙技術(shù)大會(huì)2025丨OS內(nèi)核與視窗分論壇:筑基開(kāi)源鴻蒙核心內(nèi)核,共拓視窗技術(shù)邊界

    開(kāi)源鴻蒙技術(shù)大會(huì)2025 OS內(nèi)核與視窗分論壇在湖南長(zhǎng)沙國(guó)際會(huì)議中心圓滿舉行。來(lái)自西北工業(yè)大學(xué)、浙江大學(xué)、廈門大學(xué)、華為等高校和企業(yè)的學(xué)者專家齊聚一堂,圍繞鴻蒙
    的頭像 發(fā)表于 11-20 17:29 ?881次閱讀
    開(kāi)源<b class='flag-5'>鴻蒙</b><b class='flag-5'>技術(shù)</b>大會(huì)2025丨OS<b class='flag-5'>內(nèi)核</b>與視窗分論壇:筑基開(kāi)源<b class='flag-5'>鴻蒙</b>核心<b class='flag-5'>內(nèi)核</b>,共拓視窗<b class='flag-5'>技術(shù)</b>邊界

    Task任務(wù):LuatOS實(shí)現(xiàn)“任務(wù)級(jí)并發(fā)”的核心引擎

    Task任務(wù)通過(guò)其強(qiáng)大的并發(fā)處理能力,使LuatOS能夠在單線程環(huán)境中模擬多線程執(zhí)行,通過(guò)協(xié)程的掛起與恢復(fù)機(jī)制,實(shí)現(xiàn)任務(wù)級(jí)的并行操作,顯著提升系統(tǒng)效能。 sys核心庫(kù)是LuatOS運(yùn)行框架庫(kù),也是
    的頭像 發(fā)表于 08-28 13:49 ?524次閱讀
    <b class='flag-5'>Task</b>任務(wù):LuatOS實(shí)現(xiàn)“任務(wù)級(jí)并發(fā)”的核心引擎

    揭秘LuatOS Task:多任務(wù)管理的“智能中樞”

    Task任務(wù)作為L(zhǎng)uatOS的核心組成部分,通過(guò)智能化的任務(wù)管理機(jī)制,實(shí)現(xiàn)任務(wù)的創(chuàng)建、調(diào)度與協(xié)同運(yùn)行,讓復(fù)雜應(yīng)用得以高效并行處理,滿足實(shí)時(shí)場(chǎng)景下的嚴(yán)苛需求。 sys核心庫(kù)是LuatOS運(yùn)行框架庫(kù)
    的頭像 發(fā)表于 08-28 13:48 ?660次閱讀
    揭秘LuatOS <b class='flag-5'>Task</b>:多任務(wù)管理的“智能中樞”

    開(kāi)源系統(tǒng)適配:聚徽分享國(guó)產(chǎn)工控平板在 Linux / 鴻蒙系統(tǒng)下的技術(shù)優(yōu)化

    工控平板進(jìn)行技術(shù)優(yōu)化,實(shí)現(xiàn)與 Linux、鴻蒙系統(tǒng)的高效適配,成為行業(yè)關(guān)注的焦點(diǎn)。 一、Linux 系統(tǒng)下國(guó)產(chǎn)工控平板的技術(shù)優(yōu)化 (一)內(nèi)核裁剪與定制 Linux
    的頭像 發(fā)表于 06-13 16:29 ?1076次閱讀

    鴻蒙5開(kāi)發(fā)寶藏案例分享---跨線程性能優(yōu)化指南

    ! 鴻蒙文檔里還藏著不少這樣的寶藏工具,建議大家多翻翻性能分析文檔~ 遇到坑點(diǎn)歡迎在評(píng)論區(qū)交流,一起挖寶! ? 下次遇到跨線程卡頓,別急著加班,先打開(kāi)Profiler看看吧! Keep Coding, 少寫B(tài)UG!?
    發(fā)表于 06-12 17:13

    鴻蒙5開(kāi)發(fā)寶藏案例分享---分析幀率問(wèn)題

    鴻蒙性能優(yōu)化寶藏:幀率問(wèn)題實(shí)戰(zhàn)案例解析 嘿,各位鴻蒙開(kāi)發(fā)者! 今天分享一個(gè)開(kāi)發(fā)中的大發(fā)現(xiàn)——鴻蒙官方文檔里藏著一堆超實(shí)用的性能優(yōu)化案例!這些案例不僅解決了常見(jiàn)的丟幀卡頓問(wèn)題,還附帶了詳細(xì)的分析
    發(fā)表于 06-12 17:07

    鴻蒙5開(kāi)發(fā)寶藏案例分享---應(yīng)用并發(fā)設(shè)計(jì)

    ?** 鴻蒙并發(fā)編程實(shí)戰(zhàn)指南:解鎖ArkTS多線程黑科技** 嘿,開(kāi)發(fā)者朋友們! 今天給大家扒一扒鴻蒙官方文檔里藏著的并發(fā)編程寶藏—— 100+實(shí)戰(zhàn)場(chǎng)景解決方案 !從金融理財(cái)?shù)接螒蜷_(kāi)發(fā),從折疊屏適配
    發(fā)表于 06-12 16:19

    鴻蒙5開(kāi)發(fā)寶藏案例分享---應(yīng)用架構(gòu)實(shí)戰(zhàn)技巧

    大家好! 今天咱們聊聊鴻蒙開(kāi)發(fā)中那些“官方文檔提了但實(shí)際開(kāi)發(fā)難找”的架構(gòu)設(shè)計(jì)技巧。結(jié)合官方文檔,我會(huì)用 真實(shí)代碼案例+通俗講解 ,幫你把分層架構(gòu)和線程通信落地到項(xiàng)目里,告別“理論會(huì)了,代碼不會(huì)
    發(fā)表于 06-12 16:14

    鴻蒙操作系統(tǒng)首登電腦端,華為開(kāi)啟鴻蒙辦公新時(shí)代

    2025年5月8日,華為在深圳舉辦了鴻蒙電腦技術(shù)與生態(tài)溝通會(huì),鴻蒙操作系統(tǒng)首次在電腦端亮相。這既是中國(guó)電子信息產(chǎn)業(yè)的歷史性時(shí)刻,也是華為鴻蒙辦公的新起點(diǎn)。 五年匠心打磨,
    發(fā)表于 05-08 14:20 ?6080次閱讀
    <b class='flag-5'>鴻蒙</b>操作系統(tǒng)首登電腦端,華為開(kāi)啟<b class='flag-5'>鴻蒙</b>辦公新時(shí)代

    kw45卡在Host_Task的原因?

    KW45 以從機(jī)模式運(yùn)行,安卓手機(jī)APP反復(fù)斷開(kāi)連接,偶爾會(huì)卡住kw45,這不是在連接和斷開(kāi)連接時(shí)發(fā)生的,而是在連接成功后的幾秒鐘或幾十秒。 調(diào)試分析發(fā)現(xiàn),kw45 卡在 Host_Task,o任務(wù)無(wú)法運(yùn)行。 以下是任務(wù)運(yùn)行的屏幕截圖。重復(fù)運(yùn)行屏幕截圖是Host_
    發(fā)表于 04-10 06:22

    進(jìn)程、線程、協(xié)程傻傻分不清?一文帶你徹底扒光它們的\"底褲\"!

    各位程序員朋友(和假裝懂技術(shù)的同事):如果你在面試時(shí)被問(wèn)到:\"請(qǐng)用奶茶店類比進(jìn)程、線程和協(xié)程\",而你回答:\"進(jìn)程是老板,線程是員工,協(xié)程是兼職...\"
    發(fā)表于 03-26 09:27

    請(qǐng)問(wèn)如何在Python中實(shí)現(xiàn)多線程與多進(jìn)程的協(xié)作?

    \") if __name__ == \'__main__\': # 使用多線程處理I/O任務(wù) thread = threading.Thread(target=io_task) # 使用多進(jìn)
    發(fā)表于 03-11 06:57