鸿蒙内核源码分析 (并发并行篇) 内核如何管理多个 CPU ,2024年最新面试题解析

81 阅读5分钟

每次 Tick 的到来,处理函数会去扫描这两个链表,看有没有定时器超时的任务需要执行,有则立即执行定时任务,定时任务是所有任务中优先级最高的,0 号优先级,在系列篇中有专门讲定时器任务,可自行翻看.

LOSCFG_KERNEL_SMP

if (LOSCFG_KERNEL_SMP == YES)

define LOSCFG_KERNEL_CORE_NUM LOSCFG_KERNEL_SMP_CORE_NUM //多核情况下支持的CPU核数

else

define LOSCFG_KERNEL_CORE_NUM 1 //单核配置

endif

多 CPU 核的操作系统有 3 种处理模式 (SMP+AMP+BMP) 鸿蒙实现的是 SMP 的方式

  • 非对称多处理(Asymmetric multiprocessing,AMP)每个 CPU 内核运行一个独立的操作系统或同一操作系统的独立实例(instantiation)。
  • 对称多处理(Symmetric multiprocessing,SMP)一个操作系统的实例可以同时管理所有 CPU 内核,且应用并不绑定某一个内核。
  • 混合多处理(Bound multiprocessing,BMP)一个操作系统的实例可以同时管理所有 CPU 内核,但每个应用被锁定于某个指定的核心。

宏 LOSCFG_KERNEL_SMP 表示对多 CPU 核的支持,鸿蒙默认是打开 LOSCFG_KERNEL_SMP 的。

多 CPU 核支持

鸿蒙内核对 CPU 的操作见于 los_mp.c ,因文件不大,这里把代码都贴出来了.

#if (LOSCFG_KERNEL_SMP == YES) //给参数CPU发送调度信号 VOID LOS_MpSchedule(UINT32 target)//target每位对应CPU core { UINT32 cpuid = ArchCurrCpuid(); target &= ~(1U << cpuid);//获取除了自身之外的其他CPU HalIrqSendIpi(target, LOS_MP_IPI_SCHEDULE);//向目标CPU发送调度信号,核间中断(Inter-Processor Interrupts),IPI } //硬中断唤醒处理函数 VOID OsMpWakeHandler(VOID) { /* generic wakeup ipi, do nothing / } //硬中断调度处理函数 VOID OsMpScheduleHandler(VOID) {//将调度标志设置为与唤醒功能不同,这样就可以在硬中断结束时触发调度程序。 /

  • set schedule flag to differ from wake function,
  • so that the scheduler can be triggered at the end of irq. */ OsPercpuGet()->schedFlag = INT_PEND_RESCH;//给当前Cpu贴上调度标签 } //硬中断暂停处理函数 VOID OsMpHaltHandler(VOID) { (VOID)LOS_IntLock(); OsPercpuGet()->excFlag = CPU_HALT;//让当前Cpu停止工作

while (1) {}//陷入空循环,也就是空闲状态 } //MP定时器处理函数, 递归检查所有可用任务 VOID OsMpCollectTasks(VOID) { LosTaskCB *taskCB = NULL; UINT32 taskID = 0; UINT32 ret;

/* recursive checking all the available task */ for (; taskID <= g_taskMaxNum; taskID++) { //递归检查所有可用任务 taskCB = &g_taskCBArray[taskID];

if (OsTaskIsUnused(taskCB) || OsTaskIsRunning(taskCB)) { continue; }

/* 虽然任务状态不是原子的,但此检查可能成功,但无法完成删除,此删除将在下次运行之前处理

  • though task status is not atomic, this check may success but not accomplish
  • the deletion; this deletion will be handled until the next run. */ if (taskCB->signal & SIGNAL_KILL) {//任务收到被干掉信号 ret = LOS_TaskDelete(taskID);//干掉任务,回归任务池 if (ret != LOS_OK) { PRINT_WARN("GC collect task failed err:0x%x\n", ret); } } } } //MP(multiprocessing) 多核处理器初始化 UINT32 OsMpInit(VOID) { UINT16 swtmrId;

(VOID)LOS_SwtmrCreate(OS_MP_GC_PERIOD, LOS_SWTMR_MODE_PERIOD, //创建一个周期性,持续时间为 100个tick的定时器 (SWTMR_PROC_FUNC)OsMpCollectTasks, &swtmrId, 0);//OsMpCollectTasks为超时回调函数 (VOID)LOS_SwtmrStart(swtmrId);//开始定时任务

return LOS_OK; } #endif

代码一一都加上了注解,这里再一一说明下:

1.OsMpInit

多 CPU 核的初始化, 多核情况下每个 CPU 都有各自的编号, 内核有分成主次 CPU, 0 号默认为主 CPU, OsMain () 由主 CPU 执行,被汇编代码调用。初始化只开了个定时任务,只干一件事就是回收不用的任务。回收的条件是任务是否收到了被干掉的信号。例如 shell 命令 kill 9 14 ,意思是干掉 14 号线程的信号,这个信号会被线程保存起来。可以选择自杀也可以等着被杀。这里要注意,鸿蒙有两种情况下任务不能被干掉, 一种是系统任务不能被干掉的, 第二种是正在运行状态的任务.

2. 次级 CPU 的初始化

同样由汇编代码调用,通过以下函数执行,完成每个 CPU 核的初始化

//次级CPU初始化,本函数执行的次数由次级CPU的个数决定. 例如:在四核情况下,会被执行3次, 0号通常被定义为主CPU 执行main LITE_OS_SEC_TEXT_INIT VOID secondary_cpu_start(VOID) { #if (LOSCFG_KERNEL_SMP == YES) UINT32 cpuid = ArchCurrCpuid();

OsArchMmuInitPerCPU();//每个CPU都需要初始化MMU

OsCurrTaskSet(OsGetMainTask());//设置CPU的当前任务

/* increase cpu counter */ LOS_AtomicInc(&g_ncpu); //统计CPU的数量

/* store each core's hwid */ CPU_MAP_SET(cpuid, OsHwIDGet());//存储每个CPU的 hwid HalIrqInitPercpu(); //CPU硬件中断初始化

OsCurrProcessSet(OS_PCB_FROM_PID(OsGetKernelInitProcessID())); //设置内核进程为CPU进程 OsSwtmrInit(); //定时任务初始化,每个CPU维护自己的定时器队列 OsIdleTaskCreate(); //创建空闲任务,每个CPU维护自己的任务队列 OsStart(); //本CPU正式启动在内核层的工作 while (1) { __asm volatile("wfi");//wait for Interrupt 等待中断,即下一次中断发生前都在此hold住不干活 }//类似的还有 WFE: wait for Events 等待事件,即下一次事件发生前都在此hold住不干活 #endif }

可以看出次级 CPU 有哪些初始化步骤:

  • 初始化 MMU,OsArchMmuInitPerCPU
  • 设置当前任务 OsCurrTaskSet
  • 初始化硬件中断 HalIrqInitPercpu
  • 初始化定时器队列 OsSwtmrInit
  • 创建空任务 OsIdleTaskCreate, 外面没有任务的时 CPU 就待在这个空任务里自己转圈圈.
  • 开始自己的工作流程 OsStart,正式开始工作,跑任务

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05
  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05
  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05
  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

img img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!