在macOS上用Linux syscall实现虚拟机管理
Linux内核以系统调用ABI的稳定性而闻名,这意味着内核系统调用接口的语义在发行版之间不会发生变化(除了不间断的错误修复和新功能的添加)。
Linux的这一功能已经非常完善,以至于存在Linux系统调用接口的几种替代实现。
最著名的是FreeBSD的Linuxolator,FreeBSD通过它提供了内核模块linux.ko,其中包括Linux系统调用接口。
通过更改(内核级别)进程结构中的指针,可以将FreeBSD上运行的Linux二进制文件配置为使用Linux syscall接口,而不是标准的FreeBSD接口。
在Windows上,Linux子系统、Windows子系统也可以通过捕获系统调用并将其转换为适当的Windows NT系统调用来工作。
这种方法,特别是FreeBSD的实现,是运行Linux二进制文件的一种非常易于集成的方式: 该二进制文件可以直接和直接访问主机文件系统和网络,可以使用fork和exec启动主机本机二进制文件,依此类推-由于实现中存在模块错误,因此Linux二进制文件应与本地二进制文件在行为上没有区别。
相比之下,在Mac上运行Linux二进制文件的典型方法是使用虚拟机——CPU虚拟化功能在自己的隔离空间中启动Linux内核,然后正常运行二进制文件。
这具有兼容性的优势,因为您正在运行真正的Linux,但是这意味着Linux进程与计算机的其余部分隔离: 尤其是,它通常具有自己的文件系统和网络接口,并且可以在它自己的“世界”,无法启动主机本机二进制文件或以其他方式与主机系统进行有意义的交互(实际上,这种隔离是虚拟机的关键功能)。
甚至连Mac的Docker都使用了虚拟机,因此它可以与成千上万的Dockerfile和Docker映像兼容,这些文件都假定它们在完整的Linux系统上运行。
作为与POSIX兼容的系统(实际上是4.4BSD和FreeBSD的派生产品),macOS提供了与Linux非常相似的核心功能,因此有可能提供在macOS上本地运行的Linux系统调用。 这样的系统将为macOS提供类似FreeBSD的Linuxolator功能。
尽管如此,虚拟机仍具有其优势。 虚拟机监视器所提供的界面精炼,意味着诸如任务快照,挂起之类的巧妙技巧成为可能。
通过VM提供的隔离,可以轻松控制文件可见性,内存和其他资源使用情况。 最后,特定于主机的部分可以相对通用,依靠POSIX功能和特定于主机的虚拟机管理程序接口,而不是直接挂接到主机的系统调用实现中,这将实现可移植性。
因此,我提出了一种混合实现: 在管理程序中运行的,与Linux-syscall兼容的简单unikernel,该内核与主机通信以执行网络和文件操作(使用超级调用)。
理想情况下,大部分系统调用复杂度都可以保留在Unikernel层。 unikernel旨在减少超级调用,以提高整体系统速度: 仅作为一个(经典)示例,可以将gettimeofday syscall完全在虚拟机内部实现。
完整的系统如下所示:
可能的用例:Linux二进制文件是面向未来的固定接口产品
Linux内核的发明人 Linus Torvalds 通常说“我们不会破坏用户空间”。这意味着由系统调用接口定义的内核ABI的语义不应在版本之间改变。
这是Linux的重要规则,因为内核开发人员不会与用户级代码(甚至是相当低级的代码,例如C库)协调内核版本。
这与其他系统(例如FreeBSD和macOS)形成对照,在这些系统中,新内核发行版与相关的用户空间更改紧密配合。
但是,Linux的ABI稳定性除了允许内核开发人员不参与用户空间代码外,还具有其他优势:例如,它可以轻松实现对内核的低级接口的替代,如各种支持Linux的libc实现,或者实际上绕过低级接口并直接与内核进行通信,就像针对Linux的Go编程语言一样。
另一方面,这意味着随着Linux新版本的发布,Linux syscall接口的替代实现不需要进行连续更改。
有几类程序很难在macOS上运行,例如使用FPGA或设计电子电路板所需的工具就是一个例子。
另一个是诸如GNU Compiler Collection之类的编译器:众所周知,GCC很难为macOS进行编译,并且通常受益于直接访问主机文件系统,因此在成熟的虚拟机中运行它非常麻烦。
对于这类工具,上述方法似乎是合适的:二进制文件将随其所需的特定于Linux的库一起提供,否则将作为本机应用程序运行,可以直接访问主机的文件系统,并具有直接运行主机的能力,并让主机本机二进制文件调用二进制文件(例如,可以想象运行Linux本机C编译器的macOS本机构建系统)。
可能的问题
WSL2:Microsoft最近用WSL2代替了WSL。
WSL2放弃了系统调用仿真,而转向虚拟化:与原始的WSL不同,WSL2在虚拟机中运行完整的Linux内核,其行为与macOS上的Docker非常相似。
声明的更改原因是为了提高文件系统性能并提供更好的系统调用兼容性。
应该调查这些问题在macOS上是否也会出现。
Windows具有与Linux不同的文件系统语义,并且内核缺乏诸如fork()之类的系统调用的有效实现:换句话说,可能是NT内核与Linux有所不同,而macOS内核不是。
其他工作
Noah是一个非常相似的项目:它提供了一个管理程序,可以捕获Linux系统调用并将其转换为macOS本机调用。
它有两个方面的不同:首先,系统调用仿真在虚拟机管理程序的macOS端运行,这限制了在进行超级调用之前可以完成的优化数量;更重要的是,Noah下载了整个Linux发行版,并在单独的“ Linux世界”中运行Linux二进制文件,与其他macOS的协同作用相对较小,就像传统的虚拟机一样。