WSL:失去潜力

本文探讨了Windows Subsystem for Linux (WSL) 的两个版本WSL1与WSL2之间的区别。WSL1在Windows NT内核上直接运行Linux二进制文件,而WSL2则通过轻量级虚拟机运行完整的Linux内核,从而解决了WSL1中的一些性能问题。

如果你最近几年在关注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中的L​​inux兼容性

如果不讨论各种各样的BSDs,这篇文章就不够完善。BSDs总是落后于Linux和其他商业操作系统,具有二进制级别的兼容性已经有很长时间了。我能找到的最早的问题是1995年NetBSD内核中的Linux兼容性。那是25年前,在WSL 1首次亮相之前的21年。

而且,这不仅限于Linux。 多年来,NetBSD一直支持模拟各种不同的操作系统。 对SVR4的支持始于1994年,并且暂时来说,NetBSD甚至还支持……PE / COFF二进制文件——Win32二进制文件。 因此,在某种程度上,NetBSD反向实现了WSL 1模型:它使你可以在2002年在NetBSD内核之上运行Win32二进制文件。

wsl: Failed to translate 'C:\Users\mrwang' wsl: Failed to translate 'C:\Program Files (x86)\Razer Chroma SDK\bin' wsl: Failed to translate 'C:\Program Files\Razer Chroma SDK\bin' wsl: Failed to translate 'D:\vmwre\bin\' wsl: Failed to translate 'C:\Windows\system32' wsl: Failed to translate 'C:\Windows' wsl: Failed to translate 'C:\Windows\System32\Wbem' wsl: Failed to translate 'C:\Windows\System32\WindowsPowerShell\v1.0\' wsl: Failed to translate 'C:\Windows\System32\OpenSSH\' wsl: Failed to translate 'C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common' wsl: Failed to translate 'C:\Windows\system32' wsl: Failed to translate 'C:\Windows' wsl: Failed to translate 'C:\Windows\System32\Wbem' wsl: Failed to translate 'C:\Windows\System32\WindowsPowerShell\v1.0\' wsl: Failed to translate 'C:\Windows\System32\OpenSSH\' wsl: Failed to translate 'C:\Program Files\dotnet\' wsl: Failed to translate 'C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR' wsl: Failed to translate 'C:\Program Files\Pandoc\' wsl: Failed to translate 'C:\Program Files\Git\cmd' wsl: Failed to translate 'C:\Windows\system32\config\systemprofile\AppData\Local\Microsoft\WindowsApps' wsl: Failed to translate 'C:\Program Files (x86)\Razer\ChromaBroadcast\bin' wsl: Failed to translate 'C:\Program Files\Razer\ChromaBroadcast\bin' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Programs\Python\Python311\Scripts\' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Programs\Python\Python311\' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Microsoft\WindowsApps' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Programs\Python\Python311\Scripts\' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Programs\Python\Python311\' wsl: Failed to translate 'C:\Users\mrwang\AppData\Local\Microsoft\WindowsApps' error: Found argument '-c' which wasn't expected, or isn't valid in this context USAGE: bash [OPTIONS] <SUBCOMMAND> For more information try --help
最新发布
11-20
<think> 我们正在处理用户关于WSL路径翻译失败和命令行参数'-c'错误的问题。虽然引用内容提到了Android SDK和窗口大小选择,但这些与当前问题无关,因此我们应忽略这些引用,专注于WSL相关问题。 根据用户描述,问题有两个: 1. WSL failed to translate Windows path errors: 这通常发生在尝试在WSL中访问Windows路径时,路径格式转换出现问题。 2. 'Found argument -c which wasn't expected' error: 这个错误通常表示命令行参数解析失败,可能是命令格式错误或使用了不期望的选项。 我们分别解决这两个问题。 问题1: WSL翻译Windows路径失败 在WSL中,Windows路径通常通过`/mnt/`目录挂载,例如C盘对应`/mnt/c/`。当你在WSL中直接使用Windows风格的路径(如`C:\Users\user`)时,可能会遇到转换错误。这是因为WSL不能直接识别Windows路径格式。 解决方案: 方法1:使用正确的WSL路径格式。将Windows路径转换为WSL路径,例如: `C:\Users\user` 转换为 `/mnt/c/Users/user` 方法2:如果需要在WSL命令中使用Windows路径,可以使用`wslpath`工具进行转换。例如: 将Windows路径转换为WSL路径:`wslpath "C:\Users\user"` 会输出`/mnt/c/Users/user` 注意:`wslpath`命令需要从WSL内部运行,并且需要指定转换方向(默认是自动检测,但也可以使用`-a`(自动)或`-w`(转Windows格式)等选项) 方法3:如果你在Windows命令行(如cmd或PowerShell)中运行wsl命令并传递路径参数,建议先使用`wslpath`转换,或者在WSL内部使用相对路径。 问题2: 'Found argument -c which wasn't expected'错误 这个错误通常出现在命令行工具中,当传入了一个未预期的选项`-c`时发生。常见场景: - 你可能在错误的位置使用了`-c`参数。 - 命令期望的是其他参数,而`-c`不是其有效选项。 例如,在运行某些命令时,`-c`可能被解释为“执行命令”,但在某些上下文中,它可能不被支持。 解决方案: 检查你正在运行的命令的文档,确认`-c`是否是有效选项。如果没有,那么可能是你误输入了`-c`,或者你正在尝试的命令不支持它。 常见情况: 1. 在运行`wsl`命令时,`-c`选项用于指定要运行的Linux命令。例如: `wsl -c "ls -l"` 但是注意,在WSL中,你也可以直接运行`wsl ls -l`(不需要`-c`)。所以,如果错误地使用了`-c`的位置,就会报错。 2. 另一种可能是你在尝试运行一个Linux命令,但该命令不接受`-c`选项。例如,你输入了: `some_command -c` 而`some_command`并不支持`-c`参数。 因此,请检查你输入的命令,确保`-c`出现在正确的位置,并且你使用的命令支持该选项。 结合两个问题: 用户可能在尝试在WSL中运行一个包含Windows路径和`-c`选项的命令,例如: `wsl -c "some_command C:\\path"` 这可能会导致两个问题: 1. 路径转换失败:因为`C:\\path`是Windows路径,在WSL中需要转换。 2. 参数`-c`使用错误:如果命令本身不需要`-c`,则可能会报错。 建议的通用解决方案: 在Windows命令行中运行WSL命令时,如果命令需要访问文件,最好使用WSL路径(即`/mnt/c/...`),或者将路径作为参数传递时先转换。 示例: 假设你想在WSL中运行`ls`命令列出`C:\Users\user`目录,正确的做法: 在Windows命令行中:`wsl ls /mnt/c/Users/user` 或者,如果你已经在WSL终端中,直接:`ls /mnt/c/Users/user` 如果你需要在Windows命令行中运行并传递参数,且命令需要执行多个操作,可以使用: `wsl -c "ls /mnt/c/Users/user"` 但是注意,在`wsl`命令中,`-c`后面应该是一个字符串,包含要执行的整个命令。所以,如果你的命令中需要包含空格或特殊字符,需要正确转义。 总结步骤: 1. 对于路径问题:在WSL命令中,使用`/mnt/`开头的路径来访问Windows文件系统。 2. 对于`-c`参数错误:检查命令格式,确保`-c`只在你需要执行一个字符串命令时使用,并且位置正确(紧跟在`wsl`后面)。 如果问题仍然存在,请提供具体的命令以便进一步诊断。 生成相关问题: 1. 如何在WSL中正确访问Windows文件? 2. WSL中常见的命令行参数错误有哪些? 3. 如何将Windows路径转换为WSL路径? 4. 在WSL中运行命令时,如何避免参数解析错误? </think> ### 解决 WSL 路径转换与 -c 参数错误 #### 一、WSL 翻译 Windows 路径失败 **问题原因**: WSL 无法自动转换包含空格、特殊字符或格式错误的 Windows 路径。例如路径 `C:\Program Files` 中的空格会导致解析失败。 **解决方案**: 1. **手动转换路径格式** Windows 路径 `C:\Users\Name` 需转换为 WSL 格式:`/mnt/c/Users/Name` ```bash # 正确示例:访问 Windows 的 C 盘 ls /mnt/c/Users/your_name/Documents ``` 2. **处理含空格的路径** 用引号包裹路径并转义空格: ```bash # 示例:访问 "Program Files" 目录 cd "/mnt/c/Program\ Files" ``` 3. **使用 `wslpath` 工具自动转换** 在 WSL 中运行: ```bash # 将 Windows 路径转为 WSL 路径 wslpath -u "C:\\Users\\Name\\File.txt" # 输出:/mnt/c/Users/Name/File.txt ``` --- #### 二、`Found argument -c which wasn't expected` 错误 **问题原因**: `-c` 参数未正确放置或与特定命令冲突,常见场景: - 在错误位置使用 `-c`(如 `wsl -c` 后缺少命令) - 与其他工具的参数冲突(如 `echo -c`) **解决方案**: 1. **正确使用 `wsl -c` 语法** `-c` 必须后接完整的 Linux 命令字符串: ```bash # 正确示例:通过 Windows 终端执行 Linux 命令 wsl -c "ls -l /home" ``` 2. **避免参数冲突** 若 `-c` 非首参数,需明确指定命令: ```bash # 错误:-c 位置错误 echo -c "Hello" # 正确:使用 -- 分隔参数 echo -- -c "Hello" # 输出:-c Hello ``` 3. **检查命令兼容性** 某些 Windows 原生命令(如 `find`)与 Linux 命令重名,明确指定路径: ```bash # 调用 Windows 的 find.exe /mnt/c/Windows/System32/find.exe "text" file.txt ``` --- #### **操作验证步骤** 1. 在 Windows PowerShell 中测试路径转换: ```powershell wsl -c "ls /mnt/c/Windows/System32 | grep 'kernel'" ``` 2. 在 WSL 终端中验证 `-c` 参数: ```bash # 无报错即成功 bash -c "echo 'Hello WSL'" ``` #### **预防措施** - 路径处理:始终使用 `/mnt/` 格式访问 Windows 文件 - 参数规范:复杂命令用引号包裹 `wsl -c "full_command"` - 环境检查:运行 `wsl --status` 确认 WSL 版本是否为最新 > 若问题仍存在,尝试重置 WSL: > ```powershell > wsl --shutdown > wsl --unregister Ubuntu # 替换为你的发行版名 > wsl --install -d Ubuntu > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值