进程
基本概念
进程是系统资源管理的最小单位。OpenHarmony LiteOS-A 内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间。KProcess 是内核态进程的根进程,KIdle 是其子进程)。
- 进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。
- 进程采用抢占式调理机制,采用高优先级优先+同优先级时间片轮转的调理算法。
- 进程一共有32个优先级(0-31),用户进程可配置的优先级有22个(10-31),最高优先级为10,最低优先级为31。
- 高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才华得到调理。
- 每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。
- 用户态根进程init由内核态创建,其它用户态子进程均由init进程fork而来。
进程状态阐明:
- 初始化(Init):进程正在被创建。
- 就绪(Ready):进程在就绪列表中,等候CPU调理。
- 运行(Running):进程正在运行。
- 阻塞(Pending):进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。
- 僵尸(Zombies):进程运行结束,等候父进程采取其控制块资源。
图1 进程状态迁徙示意图
进程状态迁徙阐明:
- Init→Ready: 进程创建或 fork 时,拿到对应进程控制块后进入 Init 状态,即进程初始化阶段,当该阶段完成后进程将被插入调理队列,此时进程进入就绪状态。
- Ready→Running: 进程创建后进入就绪态,发生进程切换时,就绪列表中优先级最高且得到时间片的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中另有其它线程处于就绪态,则该进程仍旧在就绪队列,此时进程的就绪态和运行态共存,但对外出现的进程状态为运行态。
- Running→Pending: 进程在末了一个线程转为阻塞态时, 进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。
- Pending→Ready: 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。
- Ready→Pending: 进程内的末了一个就绪态线程转为阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。
- Running→Ready: 进程由运行态转为就绪态的环境有以下两种:
- 有更高优先级的进程创建大概恢复后,会发生进程调理,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。
- 若进程的调理策略为 LOS_SCHED_RR(时间片轮转),且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。
- Running→Zombies: 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等候父进程采取资源。
运行机制
OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,支持用户态进程的创建、退出、资源采取、设置/获取调理参数、获取进程ID、设置/获取进程组ID等功能。
用户态进程通过fork父进程而来,fork进程时会将父进程的进程虚拟内存空间clone到子进程,子进程实际运行时通过写时复制机制将父进程的内容按需复制到子进程的虚拟内存空间。
进程只是资源管理单位,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。
图2 进程管理示意图
开发指导
接口阐明
表1 进程及进程组
接口名接口描述LOS_GetCurrProcessID获取当前进程的进程IDLOS_GetProcessGroupID获取指定进程的进程组IDLOS_GetCurrProcessGroupID获取当前进程的进程组ID 表2 用户及用户组
接口名接口描述LOS_GetUserID获取当前进程的用户IDLOS_GetGroupID获取当前进程的用户组IDLOS_CheckInGroups检查指定用户组ID是否在当前进程的用户组内 表3 进程调理控制
接口名接口LOS_GetProcessScheduler获取指定进程的调理策略LOS_SetProcessScheduler设置指定进程的调理参数,包罗优先级和调理策略LOS_SetProcessPriority设置进程优先级LOS_GetProcessPriority获取进程优先级 表4 系统进程信息获取
接口名接口描述LOS_GetSystemProcessMaximum获取系统支持的最大进程数目LOS_GetUsedPIDList得到已使用的进程ID列表 表5 进程创建与结束
接口名接口描述LOS_Fork创建子进程LOS_Wait等候子进程结束并采取子进程LOS_Waitid等候相应ID的进程结束LOS_Exit退出进程 开发流程
不支持内核态进程创建,内核态不涉及进程相干开发。
阐明:
- idle线程的数量跟随CPU核心数,每个CPU均有一个相应的idle线程。
- 不支持创建除KProcess和KIdle进程之外的其它内核态进程。
- 用户态进程通过系统调用进入内核态后创建的线程属于KProcess, 不属于当前用户态进程。
任务
基本概念
从系统的角度看,任务Task是竞争系统资源的最小运行单位。任务可以使用或等候CPU、使用内存空间等系统资源,并独立于其它任务运行。
OpenHarmony 内核中使用一个任务表现一个线程。
OpenHarmony 内核中同优先级进程内的任务同一调理、运行。
OpenHarmony 内核中的任务采用抢占式调理机制,同时支持时间片轮转调理和FIFO调理方式。
OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0,最低优先级为31。
当前进程内, 高优先级的任务可抢占低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才华得到调理。
任务状态阐明:
- 初始化(Init):任务正在被创建。
- 就绪(Ready):任务在就绪列表中,等候CPU调理。
- 运行(Running):任务正在运行。
- 阻塞(Blocked):任务被阻塞挂起。Blocked状态包罗:pending(因为锁、事件、信号量等阻塞)、suspended(主动pend)、delay(延时阻塞)、pendtime(因为锁、事件、信号量时间等超时等候)。
- 退出(Exit):任务运行结束,等候父任务采取其控制块资源。
图1 任务状态迁徙示意图
任务状态迁徙阐明:
- Init→Ready: 任务创建拿到控制块后为初始化阶段(Init状态),当任务初始化完成将任务插入调理队列,此时任务进入就绪状态。
- Ready→Running: 任务创建后进入就绪态,发生任务切换时,就绪列表中最高优先级的任务被执行,从而进入运行态,此刻该任务从就绪列表中删除。
- Running→Blocked: 正在运行的任务发生阻塞(挂起、延时、读信号量等)时,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪列表中剩余最高优先级任务。
- Blocked→Ready : 阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪列表,从而由阻塞态变成就绪态。
- Ready→Blocked: 任务也有可能在就绪态时被阻塞(挂起),此时任务状态会由就绪态变化为阻塞态,该任务从就绪列表中删除,不会参与任务调理,直到该任务被恢复。
- Running→Ready: 有更高优先级任务创建大概恢复后,会发生任务调理,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,并加入就绪列表中。
- Running→Exit: 运行中的任务运行结束,任务状态由运行态变为退出态。若为设置了分离属性( 由头文件 los_task.h 中的宏定义 LOS_TASK_STATUS_DETACHED 设置)的任务,运行结束后将直接烧毁。
运行机制
OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起和任务恢复、锁任务调理息争锁任务调理、根据ID查询任务控制块信息功能。
用户创建任务时,系统会将任务栈进行初始化,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。如许在任务第一次启动进入运行态时,将会执行任务入口函数。
开发指导
接口阐明
表1 任务的创建和删除
接口名接口描述LOS_TaskCreate创建任务,若所创建任务的优先级比当前的运行的任务优先级高且任务调理没有锁定,则该任务将被调理进入运行态LOS_TaskCreateOnly创建任务并阻塞,任务恢复前不会将其加入就绪队列中LOS_TaskDelete删除指定的任务,采取其任务控制块和任务栈所消耗的资源 表2 任务的状态控制
接口名接口描述LOS_TaskResume恢复挂起的任务LOS_TaskSuspend挂起指定的任务,该任务将从就绪任务队列中移除LOS_TaskJoin阻塞当前任务,等候指定任务运行结束并采取其资源LOS_TaskDetach修改任务的 joinable 属性为 detach 属性,detach 属性的任务运行结束会自动采取任务控制块资源LOS_TaskDelay延迟当前任务的执行,在延后指定的时间(tick数)后可以被调理LOS_TaskYield将当前任务从具有雷同优先级的任务队列,移动到就绪任务队列的末尾 表3 任务调理
接口名接口描述LOS_TaskLock锁定任务调理,制止任务切换LOS_TaskUnlock解锁任务调理。通过该接口可以使任务锁数量减1,若任务多次加锁,那么任务调理在锁数量减为0时才会完全解锁LOS_GetTaskScheduler获取指定任务的调理策略LOS_SetTaskScheduler设置指定任务的调理参数,包罗优先级和调理策略LOS_Schedule触发主动的任务调理 表4 任务相干信息获取
接口名接口描述LOS_CurTaskIDGet获取当前任务的IDLOS_TaskInfoGet获取指定任务的信息LOS_GetSystemTaskMaximum获取系统支持的最大任务数 表5 任务优先级
接口名接口描述LOS_CurTaskPriSet设置当前正在运行的任务的优先级LOS_TaskPriSet设置指定任务的优先级LOS_TaskPriGet获取指定任务的优先级 表6 任务绑核操作
接口名接口描述LOS_TaskCpuAffiSet绑定指定任务到指定CPU上运行,仅在多核下使用LOS_TaskCpuAffiGet获取指定任务的绑核信息,仅在多核下使用 开发流程
任务的典型开发流程:
- 通过LOS_TaskCreate创建一个任务。
- 指定任务的执行入口函数
- 指定任务名
- 指定任务的栈大小
- 指定任务的优先级
- 指定任务的属性,LOS_TASK_ATTR_JOINABLE和LOS_TASK_STATUS_DETACHED属性
- 多核运行时,可以选择设置任务的绑核属性
- 任务参与调理运行,执行用户指定的业务代码。
- 任务执行结束,如果设置了 LOS_TASK_STATUS_DETACHED 属性,则自动采取任务资源,如果任务设置了 LOS_TASK_ATTR_JOINABLE 属性,则需要调用LOS_TaskJoin 采取任务资源,默认为 LOS_TASK_STATUS_DETACHED 属性。
阐明:
- 内核态具有最高权限,可以操作任意进程内的任务。
- 用户态进程通过系统调用进入内核态后创建的任务属于KProcess, 不属于当前用户态进程。
编程实例
代码实现如下(该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。):
- [/code] scss
- 代码解读
- 复制代码
- UINT32 g_taskLoID; UINT32 g_taskHiID; #define TSK_PRIOR_HI 4 #define TSK_PRIOR_LO 5 UINT32 ExampleTaskHi(VOID) { UINT32 ret; PRINTK("Enter TaskHi Handler.\n"); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoID任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { PRINTK("Delay Task Failed.\n"); return LOS_NOK; } /* 2个Tick时间到了后,该任务恢复,继续执行 */ PRINTK("TaskHi LOS_TaskDelay Done.\n"); /* 挂起自身任务 */ ret = LOS_TaskSuspend(g_taskHiID); if (ret != LOS_OK) { PRINTK("Suspend TaskHi Failed.\n"); return LOS_NOK; } PRINTK("TaskHi LOS_TaskResume Success.\n"); return LOS_OK; } /* 低优先级任务入口函数 */ UINT32 ExampleTaskLo(VOID) { UINT32 ret; PRINTK("Enter TaskLo Handler.\n"); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中就高优先级的任务(配景任务) */ ret = LOS_TaskDelay(2); if (ret != LOS_OK) { PRINTK("Delay TaskLo Failed.\n"); return LOS_NOK; } PRINTK("TaskHi LOS_TaskSuspend Success.\n"); /* 恢复被挂起的任务g_taskHiID */ ret = LOS_TaskResume(g_taskHiID); if (ret != LOS_OK) { PRINTK("Resume TaskHi Failed.\n"); return LOS_NOK; } PRINTK("TaskHi LOS_TaskDelete Success.\n"); return LOS_OK; } /* 任务测试入口函数,在里面创建优先级不一样的两个任务 */ UINT32 ExampleTaskCaseEntry(VOID) { UINT32 ret; TSK_INIT_PARAM_S initParam = {0}; /* 锁任务调理 */ LOS_TaskLock(); PRINTK("LOS_TaskLock() Success!\n"); /* 高优先级任务的初始化参数,其资源采取需要其他任务调用 LOS_TaskJoin */ initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskHi; initParam.usTaskPrio = TSK_PRIOR_HI; initParam.pcName = "HIGH_NAME"; initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_ATTR_JOINABLE; /* 创建高优先级任务,由于锁任务调理,任务创建成功后不会立刻执行 */ ret = LOS_TaskCreate(&g_taskHiID, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); PRINTK("ExampleTaskHi create Failed! ret=%d\n", ret); return LOS_NOK; } PRINTK("ExampleTaskHi create Success!\n"); /* 低优先级任务的初始化参数,任务结束后会自行结束烧毁 */ initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskLo; initParam.usTaskPrio = TSK_PRIOR_LO; initParam.pcName = "LOW_NAME"; initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED; /* 创建低优先级任务,由于锁任务调理,任务创建成功后不会立刻执行 */ ret = LOS_TaskCreate(&g_taskLoID, &initParam); if (ret!= LOS_OK) { LOS_TaskUnlock(); PRINTK("ExampleTaskLo create Failed!\n"); return LOS_NOK; } PRINTK("ExampleTaskLo create Success!\n"); /* 解锁任务调理,此时会发生任务调理,执行就绪列表中最高优先级任务 */ LOS_TaskUnlock(); ret = LOS_TaskJoin(g_taskHiID, NULL); if (ret != LOS_OK) { PRINTK("Join ExampleTaskHi Failed!\n"); } else { PRINTK("Join ExampleTaskHi Success!\n"); } while(1){}; return LOS_OK; } c
- 编译运行得到的结果为:
- [code]
复制代码 erlang
代码解读
复制代码
LOS_TaskLock() Success! ExampleTaskHi create Success! ExampleTaskLo create Success! Enter TaskHi Handler. Enter TaskLo Handler. TaskHi LOS_TaskDelay Done. TaskHi LOS_TaskSuspend Success. TaskHi LOS_TaskResume Success. TaskHi LOS_TaskDelete Success. Join ExampleTaskHi Success!
DD一下:欢迎各人关注公众号<程序猿百晓生>,可以了解到一下知识点。
[code][/code] erlang
代码解读
复制代码
1.OpenHarmony开发底子 2.OpenHarmony北向开发环境搭建 3.鸿蒙南向开发环境的搭建 4.鸿蒙生态应用开发白皮书V2.0 & V3.0 5.鸿蒙开发面试真题(含参考答案) 6.TypeScript入门学习手册 7.OpenHarmony 经典面试题(含参考答案) 8.OpenHarmony设备开发入门【最新版】 9.沉浸式剖析OpenHarmony源代码 10.系统定制指南 11.【OpenHarmony】Uboot 驱动加载流程 12.OpenHarmony构建系统--GN与子系统、部件、模块详解 13.ohos开机init启动流程 14.鸿蒙版性能优化指南 .......
调理器
基本概念
OpenHarmony LiteOS-A内核采用了高优先级优先 + 同优先级时间片轮转的抢占式调理机制,系统从启动开始基于real time的时间轴向前运行,使得该调理算法具有很好的实时性。
OpenHarmony 的调理算法将 tickless 机制自然嵌入到调理算法中,一方面使得系统具有更低的功耗,另一方面也使得 tick 中断按需响应,减少无用的 tick 中断响应,进一步提高系统的实时性。
OpenHarmony 的进程调理策略支持 SCHED_RR(时间片轮转),线程调理策略支持 SCHED_RR 和 SCHED_FIFO(先辈先出)。
OpenHarmony 调理的最小单位为线程。
运行机制
OpenHarmony 采用进程优先级队列 + 线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。
图1 调理优先级桶队列示意图
OpenHarmony 在系统启动内核初始化之后开始调理,运行过程中创建的进程或线程会被加入到调理队列,系统根据进程和线程的优先级及线程的时间片消耗环境选择最优的线程进行调理运行,线程一旦调理到就会从调理队列上删除,线程在运行过程中发生阻塞,会被加入到对应的阻塞队列中并触发一次调理,调理其它线程运行。如果调理队列上没有可以调理的线程,则系统就会选择KIdle进程的线程进行调理运行。
图2 调理流程示意图
开发指导
接口阐明
接口名称描述LOS_Schedule触发系统调理LOS_GetTaskScheduler获取指定任务的调理策略LOS_SetTaskScheduler设置指定任务的调理策略LOS_GetProcessScheduler获取指定进程的调理策略LOS_SetProcessScheduler设置指定进程的调理参数,包罗优先级和调理策略 开发流程
阐明: 系统启动初始化阶段,不允许触发调理。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |