在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙內核源碼Task/線程技術分析

鴻蒙系統HarmonyOS ? 來源:oschina ? 作者:鴻蒙源碼分析系列 ? 2020-10-18 10:42 ? 次閱讀

前言

鴻蒙內核中,廣義上可理解為一個Task就是一個線程

一、怎么理解Task

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

基本概念
從系統的角度看,線程是競爭系統資源的最小運行單元。線程可以使用或等待CPU、使用內存空間等系統資源,并獨立于其它線程運行。

鴻蒙內核每個進程內的線程獨立運行、獨立調度,當前進程內線程的調度不受其它進程內線程的影響。

鴻蒙內核中的線程采用搶占式調度機制,同時支持時間片輪轉調度和FIFO調度方式。

鴻蒙內核的線程一共有32個優先級(0-31),最高優先級為0,最低優先級為31。

當前進程內高優先級的線程可搶占當前進程內低優先級線程,當前進程內低優先級線程必須在當前進程內高優先級線程阻塞或結束后才能得到調度。

線程狀態說明:

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

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

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

阻塞(Blocked):該線程被阻塞掛起。Blocked狀態包括:pend(因為鎖、事件、信號量等阻塞)、suspend(主動pend)、delay(延時阻塞)、pendtime(因為鎖、事件、信號量時間等超時等待)。

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

圖 1 線程狀態遷移示意圖

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

如何證明是一個東西,繼續再往下看。

2. 執行task命令

鴻蒙 task 命令的執行結果:

task命令 查出每個任務在生命周期內的運行情況,它運行的內存空間,優先級,時間片,入口執行函數,進程ID,狀態等等信息,非常的復雜。這么復雜的信息就需要一個結構體來承載。而這個結構體就是 LosTaskCB(任務控制塊)

對應張大爺的故事:task就是一個用戶的節目清單里的一個節目,用戶總清單就是一個進程,所以上面會有很多的節目。

3. task長得什么樣子?

說LosTaskCB之前先說下官方文檔任務狀態對應的 define,可以看出task和線程是一個東西。

#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長什么樣?抱歉,它確實有點長,但還是要全部貼出全貌。

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;

結構體LosTaskCB內容很多,各代表什么含義?

LosTaskCB相當于任務在內核中的身份證,它反映出每個任務在生命周期內的運行情況。既然是周期就會有狀態,要運行就需要內存空間,就需要被內核算法調度,被選中CPU就去執行代碼段指令,CPU要執行就需要告訴它從哪里開始執行,因為是多線程,但只有一個CPU就需要不斷的切換任務,那執行會被中斷,也需要再恢復后繼續執行,又如何保證恢復的任務執行不會出錯,這些問題都需要說明白。

二、Task怎么管理

1.什么是任務池?

前面已經說了任務是內核調度層面的概念,調度算法保證了task有序的執行,調度機制詳見其他姊妹篇的介紹。
如此多的任務怎么管理和執行?管理靠任務池和就緒隊列,執行靠調度算法。
代碼如下(OsTaskInit):

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

    g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;//任務池中最多默認128個,可謂鐵打的任務池流水的線程
    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);//任務池 常駐內存,不被釋放
    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 < g_taskMaxNum; index++) {
   
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
        g_taskCBArray[index].taskID = index;//任務ID最大默認127
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);//都插入空閑任務鏈表
    }

    ret = OsPriQueueInit();//創建32個任務優先級隊列,即32個雙向循環鏈表
    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);//每個CPU內核都有一個執行任務鏈表
        if (ret != LOS_OK) {
   
            return LOS_ERRNO_TSK_NO_MEMORY;
        }
    }
    return LOS_OK;
}

g_taskCBArray 就是個任務池,默認創建128個任務,常駐內存,不被釋放。

g_losFreeTask是空閑任務鏈表,想創建任務時來這里申請一個空閑任務,用完了就回收掉,繼續給后面的申請使用。
g_taskRecyleList是回收任務鏈表,專用來回收exit 任務,任務所占資源被確認歸還后被徹底刪除,就像員工離職一樣,得有個離職隊列和流程,要歸還電腦,郵箱,有沒有借錢要還的 等操作。

對應張大爺的故事:用戶要來場館領取表格填節目單,場館只準備了128張表格,領完就沒有了,但是節目表演完了會回收表格,這樣多了一張表格就可以給其他人領取了,這128張表格對應鴻蒙內核這就是任務池,簡單吧。

2.就緒隊列是怎么回事

CPU執行速度是很快的,鴻蒙內核默認一個時間片是 10ms, 資源有限,需要在眾多任務中來回的切換,所以絕不能讓CPU等待任務,CPU就像公司最大的領導,下面很多的部門等領導來審批,吃飯。只有大家等領導,哪有領導等你們的道理,所以工作要提前準備好,每個部門的優先級又不一樣,所以每個部門都要有個任務隊列,里面放的是領導能直接處理的任務,沒準備好的不要放進來,因為這是給CPU提前準備好的糧食!
這就是就緒隊列的原理,一共有32個就緒隊列,進程和線程都有,因為線程的優先級是默認32個, 每個隊列中放同等優先級的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)));//常駐內存,不被釋放
    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 的內存分配,就是32個LOS_DL_LIST,還記得LOS_DL_LIST的妙用嗎,不清楚的去鴻蒙源碼分析(總目錄)里面翻。

對應張大爺的故事:就是門口那些排隊的都是至少有一個節目單是符合表演標準的,資源都到位了,沒有的連排隊的資格都木有,就慢慢等吧。

3.任務棧是怎么回事

每個任務都是獨立開的,任務之間也相互獨立,之間通訊通過IPC,這里的“獨立”指的是每個任務都有自己的運行環境 —— 棧空間,稱為任務棧,??臻g里保存的信息包含局部變量、寄存器、函數參數、函數返回地址等等
但系統中只有一個CPU,任務又是獨立的,調度的本質就是CPU執行一個新task,老task在什么地方被中斷誰也不清楚,是隨機的。那如何保證老任務被再次調度選中時還能從上次被中斷的地方繼續玩下去呢?

答案是:任務上下文,CPU內有一堆的寄存器,CPU運行本質的就是這些寄存器的值不斷的變化,只要切換時把這些值保存起來,再還原回去就能保證task的連續執行,讓用戶毫無感知。鴻蒙內核給一個任務執行的時間是 20ms ,也就是說有多任務競爭的情況下,一秒鐘內最多要來回切換50次。

對應張大爺的故事:就是碰到節目沒有表演完就必須打斷的情況下,需要把當時的情況記錄下來,比如小朋友在演躲貓貓的游戲,一半不演了,張三正在樹上,李四正在廁所躲,都記錄下來,下次再回來你們上次在哪就會哪呆著去,就位了繼續表演。這樣就接上了,觀眾就木有感覺了。
任務上下文(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;

發現基本都是CPU寄存器的恢復現場值, 具體各寄存器有什么作用大家可以去網上詳查,后續也有專門的文章來介紹。這里說其中的三個寄存器 SP, LR, PC

LR
用途有二,一是保存子程序返回地址,當調用BL、BX、BLX等跳轉指令時會自動保存返回地址到LR;二是保存異常發生的異常返回地址。

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

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

4.任務棧初始化

任務棧的初始化就是任務上下文的初始化,因為任務沒開始執行,里面除了上下文不會有其他內容,注意上下文存放的位置在棧的底部。

三、Task函數集

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;//程序計數器,CPU首次執行task時跑的第一條指令位置
#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.使用場景和功能

任務創建后,內核可以執行鎖任務調度,解鎖任務調度,掛起,恢復,延時等操作,同時也可以設置任務優先級,獲取任務優先級。任務結束的時候,則進行當前任務自刪除操作。
Huawei LiteOS 系統中的任務管理模塊為用戶提供下面幾種功能。

功能分類 接口 描述
任務的創建和刪除 LOS_TaskCreateOnly 創建任務,并使該任務進入suspend狀態,并不調度。
LOS_TaskCreate 創建任務,并使該任務進入ready狀態,并調度。
LOS_TaskDelete 刪除指定的任務。
任務狀態控制 LOS_TaskResume 恢復掛起的任務。
LOS_TaskSuspend 掛起指定的任務。
LOS_TaskDelay 任務延時等待。
LOS_TaskYield 顯式放權,調整指定優先級的任務調度順序。
任務調度的控制 LOS_TaskLock 鎖任務調度。
LOS_TaskUnlock 解鎖任務調度。
任務優先級的控制 LOS_CurTaskPriSet 設置當前任務的優先級。
LOS_TaskPriSet 設置指定任務的優先級。
LOS_TaskPriGet 獲取指定任務的優先級。
任務信息獲取 LOS_CurTaskIDGet 獲取當前任務的ID。
LOS_TaskInfoGet 設置指定任務的優先級。
LOS_TaskPriGet 獲取指定任務的信息。
LOS_TaskStatusGet 獲取指定任務的狀態。
LOS_TaskNameGet 獲取指定任務的名稱。
LOS_TaskInfoMonitor 監控所有任務,獲取所有任務的信息。
LOS_NextTaskIDGet 獲取即將被調度的任務的ID。

2.創建任務的過程

創建任務之前先了解另一個結構體 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;

這些初始化參數是外露的任務初始參數,pfnTaskEntry對java來說就是你new進程的run(),需要上層使用者提供.

看個例子吧:shell中敲 ping 命令看下它創建的過程

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;//線程的執行函數
        stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//0x4000 = 16K 
        stPingTask.pcName = "ping_task";
        stPingTask.usTaskPrio = 8; /* higher than shell 優先級高于10,屬于內核態線程*/ 
        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;
}

發現ping的調度優先級是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);
}
關于shell后續會詳細介紹,請持續關注。

前置條件了解清楚后,具體看任務是如何一步步創建的,如何和進程綁定,加入調度就緒隊列,還是繼續看源碼

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 任務創建完了 申請調度
    }

    return LOS_OK;
}
對應張大爺的故事:就是節目單要怎么填,按格式來,從哪里開始演,要多大的空間,王場館好協調好現場的環境。這里注意在同一個節目單只要節目沒演完,王場館申請場地的空間就不能給別人用,這個場地空間對應的就是鴻蒙任務的??臻g,除非整個節目單都完了,就回收了。把整個場地干干凈凈的留給下一個人的節目單來表演。

至此的創建已經完成,已各就各位,源碼最后還申請了一次LOS_Schedule();因為鴻蒙的調度方式是搶占式的,如何本次task的任務優先級高于其他就緒隊列,那么接下來要執行的任務就是它了!
編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1410

    瀏覽量

    41105
  • 線程
    +關注

    關注

    0

    文章

    507

    瀏覽量

    20078
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2639

    瀏覽量

    67708
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    鴻蒙操作系統首登電腦端,華為開啟鴻蒙辦公新時代

    2025年5月8日,華為在深圳舉辦了鴻蒙電腦技術與生態溝通會,鴻蒙操作系統首次在電腦端亮相。這既是中國電子信息產業的歷史性時刻,也是華為鴻蒙辦公的新起點。 五年匠心打磨,
    發表于 05-08 14:20 ?4535次閱讀
    <b class='flag-5'>鴻蒙</b>操作系統首登電腦端,華為開啟<b class='flag-5'>鴻蒙</b>辦公新時代

    請問如何在Python中實現多線程與多進程的協作?

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

    鴻蒙文件傳輸三方庫上線開源鴻蒙社區 十行代碼實現大文件高速傳輸

    ”的推出,標志著鴻蒙生態在大文件傳輸領域邁出重要一步。通過多線程并發、斷點續傳、智能網絡適配等技術,“SFFT”不僅解決了開發者的開發痛點,更大幅提升了終端用戶的文件傳輸體驗。 目前,“SFFT”已上線
    發表于 03-06 10:29

    DevEco Studio構建分析工具Build Analyzer 為原生鴻蒙應用開發提速

    不同構建階段的性能差異,進一步優化構建流程。 Build Analyzer作為一款強大的構建分析工具,為原生鴻蒙應用開發者提供了從任務追蹤到性能優化的全方位支持。通過其細粒度的分析和直觀的可視化
    發表于 02-17 18:06

    OpenHarmony源碼編譯后燒錄鏡像教程,RK3566鴻蒙開發板演示

    本文介紹瑞芯微主板/開發板編譯OpenHarmony源碼后燒錄鏡像的教程,觸覺智能Purple Pi OH鴻蒙開發板演示。搭載了瑞芯微RK3566四核處理器,樹莓派卡片電腦設計,支持開源鴻蒙OpenHarmony3.2-5.0系
    的頭像 發表于 12-30 10:08 ?659次閱讀
    OpenHarmony<b class='flag-5'>源碼</b>編譯后燒錄鏡像教程,RK3566<b class='flag-5'>鴻蒙</b>開發板演示

    鴻蒙系統生態設備突破10億臺 超過15000個鴻蒙原生應用和元服務上架

    從操作系統內核、文件系統,到編程語言、人工智能框架和大模型等全部實現自研;放棄了傳統的Linux內核以及安卓開源代碼項目AOSP,僅支持鴻蒙內核
    的頭像 發表于 10-23 16:43 ?1767次閱讀

    鴻蒙Flutter實戰:07混合開發

    。 其優點是主項目開發者可以不關注Flutter實現,不需要安裝配置Flutter開發環境,缺點是無法及時修改Flutter代碼,也不存在熱重載。 ## 2.基于源碼 通過源碼依賴的當時,在原生鴻蒙
    發表于 10-23 16:00

    【免費分享】OpenHarmony鴻蒙物聯網開發板資料包一網打盡,附教程/視頻/項目/源碼...

    ?想要深入學習鴻蒙設備開發及鴻蒙物聯網開發嗎?現在機會來了!我們為初學者們準備了一份全面的資料包,包括原理圖、教程、視頻、項目、源碼等,所有資料全部免費領取,課程視頻可試看(購買后看完整版),讓你
    的頭像 發表于 09-14 14:09 ?793次閱讀
    【免費分享】OpenHarmony<b class='flag-5'>鴻蒙</b>物聯網開發板資料包一網打盡,附教程/視頻/項目/<b class='flag-5'>源碼</b>...

    CPU線程和程序線程的區別

    CPU的線程與程序的線程在概念、作用、實現方式以及性能影響等方面存在顯著差異。以下是對兩者區別的詳細闡述,旨在深入探討這一技術話題。
    的頭像 發表于 09-02 11:18 ?1928次閱讀

    Linux內核測試技術

    。內核測試技術是實現這一目標的關鍵手段。本文將詳細介紹 Linux 內核測試的各種技術,包括單元測試、集成測試、功能測試和性能測試等,并討論不同測試方法的優缺點及其適用場景。
    的頭像 發表于 08-13 13:42 ?911次閱讀
    Linux<b class='flag-5'>內核</b>測試<b class='flag-5'>技術</b>

    鴻蒙OpenHarmony南向/北向快速開發教程-迅為RK3568開發板

    P13_vendor和device目錄介紹 P14_內核編譯腳本構建分析 P15_內核移植 P16_內核移植優化 P17_配置電源管理芯片和點亮HDMI屏幕 P18_
    發表于 07-23 10:44

    華為鴻蒙內核獲中國信通院自主成熟度A級認證

    在科技創新的浪潮中,華為再次以其卓越的自主研發能力引領行業前行。近日,中國信息通信研究院(簡稱“中國信通院”)官方公眾號宣布了一項重要成果:華為技術有限公司的鴻蒙內核成功通過了自主成熟度等級認證
    的頭像 發表于 07-03 14:32 ?957次閱讀

    歡創播報 華為宣布鴻蒙內核已超越Linux內核

    1 華為宣布鴻蒙內核已超越Linux內核 ? 6月21日,在華為開發者大會上, HarmonyOS NEXT(鴻蒙NEXT)——真正獨立于安卓和iOS的
    的頭像 發表于 06-27 11:30 ?1161次閱讀

    鴻蒙開發:線程模型

    FA模型下的線程主要有如下三類
    的頭像 發表于 06-24 17:27 ?657次閱讀
    <b class='flag-5'>鴻蒙</b>開發:<b class='flag-5'>線程</b>模型

    鴻蒙開發:【線程模型】

    管理其他線程的ArkTS引擎實例,例如使用TaskPool(任務池)創建任務或取消任務、啟動和終止Worker線程。
    的頭像 發表于 06-13 16:38 ?663次閱讀
    <b class='flag-5'>鴻蒙</b>開發:【<b class='flag-5'>線程</b>模型】
    主站蜘蛛池模板: 午夜大片男女免费观看爽爽爽尤物 | 亚洲韩国欧美一区二区三区 | 色多多视频官网 | 啪啪调教所29下拉式免费阅读 | 欧美性猛交xxxx乱大交高清 | 国产一区二区三区在线影院 | 国产免费久久精品99久久 | 精品免费久久久久久成人影院 | 人人干国产| 一个人看aaaa免费中文 | 免费视频在线视频观看1 | 免费网站黄 | 亚洲香蕉久久 | 国产一级特黄一级毛片 | 视频在线精品 | 国产毛片久久国产 | 奇米影色777四色在线首页 | 六月婷婷网视频在线观看 | 久久亚洲国产精品五月天 | 性做久久久久久久免费观看 | 欧美在线视频播放 | 69老司机亚洲精品一区 | 美女扒尿口给男人桶到爽 | 日本理论片www视频 日本理论午夜中文字幕第一页 | 91精品国产亚洲爽啪在线影院 | 日本网站黄色 | 手机在线观看a | 伊人网综合视频 | 国产又大又黄又粗又爽 | 欧美大片一区 | 手机天堂网 | 四虎影院国产精品 | 欧美成人精品 | 夜夜艹| 亚洲一区毛片 | 精品视频卡1卡2卡3 精品视频免费看 | 一级做a爰片久久毛片人呢 一级做a爰片久久毛片图片 | 干成人网| 日韩精品一区二区在线观看 | 久久久免费精品 | 正在播放国产乱子伦视频 |