WSL:失去潜力
如果你最近几年在关注windows10系统,你应该知道Windows Subsystem for Linux,或者简称为WSL是周边开发人员的热门话题。最终你可以在Windows上以一等公民的身份运行你的Linux工具,这意味着你无需学习PowerShell或忍受古老的CMD.EXE
控制台。
不幸的是,并非一切都像听起来那么美好。作为Azure新角色的一部分,我现在必须在Windows上开发。WSL仍然与本机Windows环境分开的事实表明了:即使我满怀希望,我也不能将WSL用作日常开发环境,因为我需要与“本地” Windows工具进行交互。
我相信事情不必如此,但是随着最近WSL 2的推出。我认为,替代世界的潜力已经消失。 但是,这是什么意思呢? 为此,我们必须首先了解WSL 1和WSL 2之间的区别以及对WSL 2的推动可能会关闭一些有趣的(技术)路径。
免责声明: 我对WSL团队中正在发生的事情或他们的未来计划一无所知。 这纯粹是基于我作为用户所经历的个人观点。
WSL 1体系结构回顾
让我们先看看WSL 1,为此,我们必须看看这个令人尴尬的名字中有什么。为什么这个功能被命名为Windows subsystem… for Linux?这不是说反了吗?这并不是Linux中的子系统,它不能执行与Windows相关的任何事情;事情正好相反!
额。你看,如果考虑到Windows NT内核的设计,那么该名称在技术上是正确的。从维基百科的Windows NT 架构页面,我们(其实就是我)找到如下内容:
Windows NT中的用户模式由子系统组成,这些子系统能够通过使用I/O管理器将I/O请求传递到适当的内核模式设备驱动程序。Window NT的用户层由“环境子系统”组成,该子系统可以运行许多不同类型的操作系统编写的应用程序,以及集成子系统,它代表环境子系统运行系统特定的功能。内核模式阻止用户模式服务和应用程序访问它们不应该访问的操作系统的关键区域。
Windows NT是从头开始设计的,旨在支持多个操作系统中正在运行的进程,而Win32则“仅仅是”这些环境子系统之一。有了这些坚实的基础,WSL 1提供了一个新的环境子系统——Linux子系统,用于在Windows NT内核上运行Linux二进制文件。Win32和Linux子系统共享公共的集成子系统。
呐,这到底意味着什么?
不同的系统调用前端,这就是它的意思。用户空间进程是二进制指令的集合,处理器不间断地执行这些指令(不考虑中断)。操作系统的内核不知道进程在做什么,直到进程发出系统调用: 这时,内核重新获得代表用户执行操作的控制权,可以是读取文件或暂停几秒钟。
进程发出系统调用的方式以及这些系统调用的语义都是特定于操作系统的。例如,在旧的x86上:在Win32上打开一个文件是通过INT 2Eh调用的系统调用号17h,而在Linux上打开一个文件是通过INT 80h调用的系统调用号5h。
但是…从概念上讲,打开文件就是打开文件,对吗? 它们之间系统调用号或软件中断号不同,事实并不是特别有趣。 这就是WSL 1的关键设计方面:简单地说,NT内核中的Linux子系统是在NT内核前面的Linux系统调用层的实现。 这些系统调用以后将委托给NT内核,而不是Win32调用。 重复这一点很重要:没有从Linux到Win32系统调用的转换。
考虑到在WSL 1下,一般如何对Linux应用程序提供良好的支持,以及NT在内部与Unix的不同方面(fork + exec是永恒的敌人),这是一项工程技术的壮举。
该设计的真正优点在于,机器上运行的是单个内核,并且该内核具有其下所有进程的整体视图。 内核了解有关Win32和Linux进程的所有信息。 这些进程都与统一资源进行交互,例如单个网络堆栈,单个内存管理器和单个进程调度程序。
WSL 2产生的原因
WSL 1如此的酷,为什么还要有WSL 2呢?有以下两点原因:
- 本质上,WSL 1必须“逐位”实现Linux的所有内核ABI。 如果该接口中存在错误,则WSL 1必须对其进行复制。 并且,如果某个功能很难在NT内核中表示,则该功能将无法实现,或者需要额外的内核逻辑(因此会变得更慢)。
- WSL 1中的Linux子系统必须遵守NT内核与传统Unix设计之间存在的任何“限制”和固有差异。 最明显的是NTFS文件系统及其语义,以及这些差异如何损害Linux二进制文件的性能。 文件系统性能差似乎是WSL 1中的常见抱怨。
WSL 2丢弃了所有的Linux子系统部分,并用一个成熟的(但隐藏得非常好且快速的)虚拟机替换了所有内容。然后,虚拟机在其中运行一个合适的Linux内核、一个合适的Linux文件系统和一个合适的Linux网络堆栈。
这意味着WSL 1设计美学已经消失了:Windows NT内核不再能看到Linux世界中发生的任何事情。 它所知道的是,内部有一个大的黑匣子(虚拟机)在其中进行“填充”,并且看到的只是虚拟机的VMENTER和VMEXIT挂钩点以及虚拟磁盘上的块级读/写请求。 NT内核现在不知道Linux进程和文件访问。 同样,Linux内核也不能了解NT领域中的任何内容。
您可以在官方文档中了解更多差异。
失去的潜力
从用户的角度来看,WSL 2感觉更好:Linux应用程序现在运行得快得多,因为它们不受NT内核中笨拙的Linux系统调用的“模拟”。 如果很难将NTFS与Linux语义结合使用,那没有问题,因为Linux环境现在在虚拟磁盘上使用ext4。 而且对Linux应用程序的支持可以更加完善,因为WSL 2是Linux:如果您想用FUSE命名,就可以了。
但这是以WSL的代价为代价的:
- 你能想象如果你可以在WSL会话中键入ps或top并看到Linux和Windows进程并排运行,并能够通过kill改变它们的状态时,会有多酷?
- 你能想象从WSL会话操纵Windows服务会有多酷吗?
- 你能想象如果你可以在WSL会话中使用ifconfig(等待,是ip吗?)来检查和修改计算机的网络接口,那有多酷?
- 本质上,您是否可以想象在WSL中执行所有Windows系统管理任务?
尽管这从未存在过,但我可以想象得到这样一个世界……而这是只有WSL 1设计才能提供的世界。 我能想到的原因是因为macOS为您提供了这种模型(尽管是因为macOS本质上是Unix)。
这就是让我感到沮丧的原因:即使我可以在用于Azure的开发计算机上安装WSL,也无法使用它。 我仍然必须通过CMD.EXE与系统进行交互,因为我必须处理Windows本地进程和资源,并且因为我必须处理的工具仅适用于Windows。
WSL 2的FAQ声称不会放弃WSL 1,如果我们遵守Microsoft的向后兼容性保证,那可能是正确的。 但是由于需要跟上Linux的变化,保持WSL 1的运行是一项艰巨的工作。 无论如何,我希望情况确实如此,WSL 1继续存在。 谁知道,也许WSL 1落后的原因是追求我所描述的这个神奇的世界? 🤔
附录:BSD中的Linux兼容性
如果不讨论各种各样的BSDs,这篇文章就不够完善。BSDs总是落后于Linux和其他商业操作系统,具有二进制级别的兼容性已经有很长时间了。我能找到的最早的问题是1995年NetBSD内核中的Linux兼容性。那是25年前,在WSL 1首次亮相之前的21年。
而且,这不仅限于Linux。 多年来,NetBSD一直支持模拟各种不同的操作系统。 对SVR4的支持始于1994年,并且暂时来说,NetBSD甚至还支持……PE / COFF二进制文件——Win32二进制文件。 因此,在某种程度上,NetBSD反向实现了WSL 1模型:它使你可以在2002年在NetBSD内核之上运行Win32二进制文件。