跳转至

HOS 内核

简要来说,HOS 内核是一个微内核,所有服务和程序都在用户空间中运行,它们之间进行通信的主要方式是通过 HIPC(此处不展开介绍);此外,大多数原语都以通过 svc #imm 调用的系统调用形式存在。该内核同时支持 32 位和 64 位程序,并且能够为生成的进程使用 32、36 和 39 位的地址空间。其大部分网络协议栈基于 FreeBSD 的网络协议栈。

模拟器实现了与 HOS 内核本身相关的大多数系统调用。当我们谈论 HOS 内核(在模拟器的上下文中)时,我们严格指的是处理系统调用的机制(及其后续副作用,例如页表的簿记)。模拟器目前无法加载自定义的低层内核并执行主管级模拟。

NX 中的大多数程序最终都会调用一个 svc,根据其立即值,该调用将被分派到特定的系统调用处理程序之一。

这些可以在 svc.cpp 中看到。所有这些都对应着用户空间程序可以执行的系统调用。

反过来,这些系统调用创建了允许程序使用 CMIF/TIPC 作为其主要的 IPC 形式来联系系统上运行的其他服务/进程的机制,其细节在此不再赘述,但你可以查阅相关的 SwitchBrew 文章:'HIPC'。

从程序的角度来看,模拟器无需处理任何特殊设备(例如 PCIE、Realtek 驱动、蓝牙或 USB);这是因为大多数有趣的事情发生在诸如 usb:u 或 pcie 服务等专门服务中。而这些服务(尚)未被模拟。

由于系统调用的性质,许多系统调用会与内存交互。模拟内核有一个内部的树状结构,借鉴自 FreeBSD 的侵入式红黑树;该结构用于跟踪和查找已添加或移除的映射。因此,大部分进程空间都是以这种方式模拟的。

从传统意义上讲,内核维护自己的独立页表,每个进程都有自己的页表,HOS 也是如此。

每个进程都自行跟踪以下结构:

  • 名称(13 个字符)
  • 64 位 ID
  • 句柄表
  • 独占监视器
  • 线程
  • 持有的锁
  • 线程本地页
  • 每个进程的页表

模拟器自愿限制自己仅使用 4 个线程(以模拟 4 个核心),这是因为大多数现有应用程序并不能从增加的核心数量中大大受益,反而可能因额外的争用而产生不利影响。这大致相当于每个进程有 4 个 ArmInterface 槽位,这些槽位随后被重定向到在该核心上运行的最后一个线程的最后一个 pc 所在位置;接着运行它,然后在返回(由于暂停或中断)时,继续重新调度该线程。

当前的调度器并非 100% 忠于原始调度器(例如,原始调度器是协作式的,而不是抢占式的),并且存在很大的时序差异(尤其是因为模拟器可以在时序差异极大的系统上运行)。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 eg/Eglantine