Genode OS框架20.11

2020-11-29 15:07:58

在Genode 20.11中,我们专注于实际应用程序工作负载的可伸缩性,并培养了Genode对64位ARM硬件的支持。因此,我们遵循的首要目标是在各种外形尺寸的设备上运行高度复杂的基于Genode的系统。

当谈到实际工作负载时,我们承认我们不能总是知道应用程序的确切行为。系统必须妥善处理许多未知因素:线程的角色和CPU强度,应用程序代码与I / O的相互作用,内存压力情况或本来非常有用的代码的突然脆弱性。必须始终预见最坏的情况。在传统的操作系统中,这意味着OS内核需要了解应用程序的某些行为模式,并且必须基于启发式决策。考虑一下CPU调度,CPU内核之间的负载平衡,驱动硬件的节能功能,内存交换,缓存以及对诸如OOM之类的致命故障做出响应。

Genode允许我们将内核之外的复杂启发式方法转移到专用组件中。 “ CPU负载平衡”一节中介绍的新CPU平衡器是我们这种方法的生动体现。使用此可选组件,Genode系统的一部分可以经受任意复杂度的CPU负载平衡策略,而不会影响无关组件的服务质量,也不会污染操作系统内核。

实际工作负载的第二个方面是它们通常不是为Genode设计的。为了适应经过时间考验的大量应用程序,我们需要弥合过时的API(认为是POSIX)与Genode的clean-slate接口之间的巨大差距。 C运行时/ VFS中简化的ioctl处理部分将展示当前版本如何利用我们新颖的VFS概念模拟传统的基于ioctl的接口。因此,在不影响Genode的体系结构优势的情况下,有用的现有应用程序开始使用。

在平台方面,新版本继续执行我们的使命,即在64位ARM硬件上托管基于Genode的系统,例如Sculpt OS。这项工作需要对设备驱动程序和整个驱动程序体系结构进行大量开发。在64位ARM硬件(i.MX8 EVK)上的Sculpt OS部分中报告了将Sculpt引入64位i.MX8硬件的成就。正如我们在ARM的多核虚拟化部分中概述的那样,此工作线几乎与我们针对ARM的自定义虚拟机监视器的改进并驾齐驱。

在工作负载未知或过于复杂的动态场景中,可能希望通过CPU迁移负载。例如,如果将POSIX软件移植到Genode,通常不会计划线程和进程的数量和角色。在当前版本中,我们添加了为此类动态方案指定的可选CPU服务。称为CPU平衡器的新组件能够监视线程及其利用率行为。根据配置的策略,平衡器可以通过CPU会话接口指示Genode的核心在CPU之间迁移线程。

此功能需要一个支持线程迁移的内核,包括Fiasco.OC,seL4和某种程度上的NOVA内核。对于NOVA内核,只能迁移具有附加调度上下文的线程,它们是Genode :: Thread和POSIX pthread实例。不支持Genode的入口点和虚拟CPU实例。

可以通过位于repos / os / run / cpu_balancer.run中的方案测试该功能。有关策略配置,Sculpt 20.08中的演示集成以及截屏视频的更多信息,可作为专用的CPU平衡器文章。

在过去的一年中,Genode对ARM 64位硬件的支持投入了大量精力。随后的下一步是将Sculpt OS移植到i.MX8 EVK板上,到目前为止,我们已将其用作参考平台。在当前版本中,我们自豪地展示了此板的Sculpt OS的第一个版本。

与原始的x86 PC变体相比,该第一个ARM版本在驱动程序子系统内部附带了一组静态设备。没有设备管理器组件会探测所使用的硬件并按需启动驱动程序。相反,使用drivers_managed-imx8q_evk软件包中定义的一组驱动程序,USB HID设备可以使用连接到该板上的鼠标和键盘外围设备。它可以驱动SD卡,该卡可以用作Genode仓库包装管理的存储后端。最后,它包含用于管理显示引擎和平台设备资源的驱动程序。

借助适用于ARM 64位的Sculpt OS,我们不仅针对经典的台式机/笔记本电脑系统(如x86),还针对嵌入式消费类硬件(如手机和平板电脑)。为了利用此目标,我们在Genode的i.MX8平台上启用了对恩智浦MX8_DSI_OLED1显示器的支持。该面板具有OLED显示屏以及符合Synaptics RMI4的触摸屏。

我们与20.02版一起发布的Genode的i.MX8显示驱动器仅支持HDMI设备,而OLED显示器则通过MIPI DSI连接到SoC。因此,我们通过MIPI DSI基础架构以及OLED显示器的实际驱动器扩展了显示驱动器。事实证明,这项工作非常艰难,我们已在Genodians网站上详细记录了该工作。

为了启用触摸屏设备,我们从头开始实现了一个新的Genode组件。触摸屏通过I2C总线连接到SoC,可以在该SoC上发送和接收数据。目前,I2C实现隐藏在驱动程序中,但是随着更多设备需要I2C访问,它最终将成为独立组件。中断是通过GPIO引脚从触摸屏传递到SoC的,因此有必要在Genode的通用i.MX GPIO驱动程序中启用i.MX8支持。我们以此为契机,简化,清理并使驱动程序更强大。此外,所有驱动程序组件现在都利用20.05版中引入的用于ARM的新平台驱动程序API。

以目前的形式,用于显示管理的驱动程序无法在HDMI或MIPI-DSI连接的显示器之间动态切换。因此,必须在帧缓冲区配置中手动配置要在Sculpt中使用的显示。默认情况下,使用HDMI连接器。

除了驱动程序子系统之外,几乎没有任何组件依赖于实际的硬件,这就是为什么Sculpt桌面的外观与x86 PC版本实际上没有区别的原因,但以下情况除外:

选择网络配置对话框时,由于缺少硬件,因此将没有“ Wifi”选项。但是,“有线”选项允许您启动i.MX FEC以太网设备的相应驱动程序。与Sculpt OS x86 PC变体的第二个区别是,目前没有虚拟机解决方案。尽管Genode包括针对ARM的成熟的虚拟机监控器解决方案-请参阅“ ARM上的多核虚拟化”部分-它仍然缺少合理的存储后端。因此,我们暂时不在虚拟化范围之内。最后,由于无法使用所需的管理组件(i.MX8的驱动程序管理器),因此无法使用USB块设备。与即将推出的Genode发行版相比,我们计划弥合与x86版本相比尚余的空白。

要尝试Sculpt在i.MX8 EVK板上尝试,您必须像往常一样启动著名的Sculpt运行脚本,但要使用base-hw内核。例如:

在后台,运行脚本从仓库软件包系统请求特定于Sculpt- 的软件包。当前,sculpt-pc和sculpt-imx8q_evk可用。

从头开始编写的针对ARMv8上的Genode的虚拟化解决方案正好在一年前发布了19.11版。从那时起,其中进行了一些改进和验证。添加了对VirtIO网络和控制台模型的支持。此外,它与我们先前的现有ARMv7虚拟机管理程序和虚拟机监视器(VMM)相简化。但是,尽管VMM的体系结构从一开始就考虑了多个虚拟CPU(VCPU),但尚未解决或测试在多个内核上运行VM的问题。

在此版本中,我们增强了作为ARM虚拟机管理程序的base-hw内核的虚拟化支持,以支持多核虚拟机。 VMM实施得到扩展,可以为VM拥有的每个VCPU启动一个入口点。这些入口点的关联性配置为分布在VMM可用的所有物理CPU上。处理VCPU事件的入口点的关联会自动用作VCPU本身的关联。每当需要处理VCPU出口时,都将其委派给在同一CPU上运行的VMM入口点。一旦VMM的入口点成功处理了退出原因,它将恢复VCPU。

以前,启动或停止VCPU的控制由运行在第一个CPU上的内核的VM服务实现。但这意味着运行在不同CPU上的所有不同VMM入口点都需要频繁调用第一个CPU上的核心服务入口点,从而导致昂贵的跨CPU通信。内核的入口点使用系统调用来指示相应目标CPU的内核内部调度程序这一事实进一步放大了这一点,这又可能会以远程CPU为目标。为了简化实现并提高性能,我们稍微扩展了VM会话接口,以返回特定于内核的功能,直接处理VCPU。借助此功能,VMM的入口点能够直接调用内核以启动或停止VCPU,而无需使用内核间接访问。但是,是否直接调用内核的详细信息隐藏在VM会话客户端API的后面,并且对用户透明。

我们改进了对对齐内存分配的支持,以修复偶发的内存泄漏,这种情况是在我们的Falkon Web浏览器端口发生的。一个相关的更改是posix_memalign()函数的实现,另一个更改是,匿名mmap()分配的地址对齐现在可以如下配置:

即使Genode使用C ++作为其主要编程语言,我们也不依赖或使用Genode OS框架内的任何C ++标准库。但是,由于C ++ STL是使用C ++进行应用程序编程的重要组成部分,因此我们为在基础框架之上构建的应用程序提供了一个。特别是GNU C ++ STL库(libstdc ++)。它被视为常规的第三方库,其功能可以按需扩展。这种方法效果很好,甚至可以使更大的基于C ++的软件(例如Qt5和Chromium的Blink引擎(作为QtWebEngine的一部分))在Genode上运行。话虽这么说,对于在Genode上使用libstdc ++的开发人员来说,尚不清楚,哪些功能受支持,哪些功能不受支持。

幸运的是,libstdc ++包含一个测试套件,顾名思义,该套件可在给定平台上测试该库的功能范围。因此,我们转向它来建立支持功能的基线。我们对请求C ++ 17时端口的行为特别感兴趣。不言而喻,这仅包括测试套件专门探究的方面。我们没有向测试套件添加全面的Genode支持,而是选择提供一种模仿通用unix目标的环境,并允许我们通过常规Linux主机OS在Linux版本的Genode上执行测试套件。它使用Genode工具链来编译测试,并生成Genode基本Linux系统来执行它们。

执行测试套件是一个反复的过程,因为在开始时,我们遇到了许多错误地失败的测试。一方面,大多数是由于C ++在Genode中的应用方式,或者是我们的构建系统在内部工作的方式。首先,Genode上的libsupc ++是cxx库的一部分。该库又是ldso.lib.so(提供基本API的动态链接器)的一部分。由于构建系统使用从包含给定共享库的ABI的符号文件生成的存根库,因此每个丢失的符号都必须可用。否则,链接步骤将因抱怨未定义的引用而失败,因为组件在编译期间使用了这些存根库。另一方面,我们必须对测试套件的基础测试框架感到满意,才能使测试环境变得更加整洁。

对于测试套件,遗漏了很多符号,因为到目前为止我们在工作负载中还没有遇到过这些符号,因此这些符号也不属于符号文件。毕竟,模板将始终生成难以预见的特定符号。除此之外,我们缺乏对对齐的new和delete运算符的支持。有了这些适应措施,我们就能够成功执行测试套件。

最后,结果描绘了一个好画面。当前的缺点归结为

由于尚未移植stdc ++ fs库,因此不支持该库。

为了正确的功能,各种子系统(std :: thread,std :: random_device,数字库)需要进一步关注。这对于失败的执行测试最为突出,在执行测试中,有时线程似乎卡住了。

CBE是一个用于管理加密块设备的库,该库完全用SPARK编写。它首次发布并与Genode 19.11集成,并通过Genode 20.05达到了功能完善性,并且已收到版本为20.08的高度模块化的后端系统。对于此版本,我们彻底简化了CBE存储库,增加了增强的自动化质量保证,并切换到另一个默认的加密后端。

一般而言,CBE储存库中的所有内容都不属于基于SPARK的核心逻辑(cbe,cbe_common和哈希算法),基于SPARK的基本工具(初始化,检查)或Ada-基于C ++的绑定(* _cxx库)。整个特定于Ge​​node的集成,测试和包装已移至Genode的gems存储库,而以前的Genode子存储库cbe被新的CBE port gems / ports / cbe.port取代。我们还借此机会删除了早期开发阶段的许多未使用的残余物,并大大简化了与CBE相关的软件包的生态系统。

我们希望这可以使CBE项目的某些特征(例如其强大的OS独立性或完全“流模式”可证明的核心逻辑)变得更加清晰,与此同时,特定于Ge​​node的附件可以从中受益是Genode主线开发的一部分。

CBE测试器是一个可编写脚本的环境,旨在测试CBE库及其基本工具的所有方面。通过其XML命令界面,不仅可以访问和验证CBE设备的数据,还可以对其进行初始化,检查其一致性,分析其元数据,执行性能基准测试,管理设备快照,对CBE设备进行在线重新键入或在线重新设置尺寸设备,最后但并非最不重要的是,管理所需的信任锚。

在此版本之前,CBE测试仪仅是一个拼凑的解决方案,并且上述许多功能都受到限制甚至缺失。例如,块访问仅以同步方式发布,对Trust-Anchor进行隐式管理,并且无法验证读取的数据。除了添加缺少的功能之外,我们还对组件进行了完全的重新设计,以遵循简洁易懂的实现概念。新的CBE测试器与运行脚本gems / run / cbe_tester.run一起提供,该脚本将既演示如何使用该测试器,又作为CBE的广泛自动化测试和基准。

此外,我们创建了特定于CBE的自动驾驶仪工具tool / cbe_autopilot,旨在为CBE版本的质量以及它们在Genode中的集成建立通用参考。在不带参数的情况下运行该工具将说明如何使用它。简而言之,当运行tool / cbe_autopilot基础时,该工具将通过GNAT验证预期可证明的内容,运行所有预期有效的与CBE相关的运行脚本,并构建所有与CBE相关的软件包(现有的build和depot目录不存在)在这个过程中感动)。这个想法是在推进CBE存储库的master分支或在Genode中发布集成的新版本之前,使测试的成功执行成为强制性的。该工具的一个便利功能是可以运行tool / cbe_autopilot证明仅执行GNAT证明部分。最后使用tool / cbe_autopilot清理,该工具清理其所有工件。

在以前的Genode版本中,为CBE后端引入了VFS插件,这使得互换具体实现变得容易得多。这促使我们在优化执行时间方面进行了一些尝试。事实证明,特别是块加密后端的选择对CBE块操作的整体性能有重大影响。此外,似乎尤其是libsparkcrypto库(我们以前的块加密默认库)将其他质量放在性能之上。

就是说,总的来说,我们希望使知情的用户能够为他或她自己决定在这种算法中谁更喜欢哪些质量。 VFS插件机制对此表示敬意。对于我们来说,将基于SPARK的块设备管理与基于SPARK的加密后端(如libsparkcrypto)相结合似乎也很自然。但是对于我们的默认用例,我们得出的结论是libcrypto库可能是一个更好的选择。

Genode版本19.11引入了通过伪文件对ioctl操作进行仿真的功能。此功能最初由终端使用。在当前版本中,我们进一步将这种机制用于其他ioctl操作,例如与块设备相关的I / O控件,因为长期计划是从Vfs :: File_io_services API中完全删除ioctl的概念。

因此,我们为块VFS-plugin配备了一个复合目录,该目录托管用于触发设备操作的伪文件:

该文件包含构造为块XML节点的设备信息,该XML节点具有提供使用的块大小以及块总数的大小和计数属性。

此外,我们将libc中现有的ioctl处理方法拆分为用于处理终端和块设备的特定方法,因为在某些时候将遵循更多不同的I / O控件组。

跟随的第一个是SNDCTL组。该组处理音频设备,并对应于几年前OpenSoundSystem(OSS)规范设定的标准。与终端和块I / O控件一样,声音控件是通过属性文件实现的。

当前实现的控件是cmus的OSS输出插件所使用的控件,cmus是该实现背后的驱动因素,它使用(过时)版本3 API。

目前,无法设置或更改任何参数。如果请求的设置与基础音频输出会话的参数不同-与OSS手册中的建议相反-我们不会默默地调整返回给被调用方的参数,而是让I / O控制操作失败。

设置通道数。我们在此处返回可用频道,如果与请求的频道数不同,则返回ENOTSUP。

返回可以写入而不会阻塞的播放数据量。现在,它等于音频输出会话的流缓冲区中剩余的空间。

应该重置设备

......