Windows-的-Linux-子系统学习手册-全-
Windows 的 Linux 子系统学习手册(全)
原文:Learn Windows Subsystem for Linux
协议:CC BY-NC-SA 4.0
一、WSL 入门
Windows Subsystem for Linux (WSL)不是 Windows 操作系统中存在的第一个子系统;相反,它是多年来开发与主机操作系统分离的应用沙箱隔离子系统的研究的更完善的产品。
在我们深入探讨 Linux 的 Windows 子系统的设置、配置和工作方式之前,让我们先看看它是如何开始的,然后快速浏览一些关键词和定义,这将使我们进入同一页面,并帮助我们阅读本书的各个章节。
本章的 WSL 初级读本肯定会有所帮助,但是如果你想直接进入设置和实际操作,现在可以跳过它。
Windows 子系统的历史
自 Microsoft Windows NT 的初始版本以来,操作系统被设计为允许一个或多个子系统在操作系统中共存,这些子系统独立于内核中的实现。这允许我们在 Win32 子系统中的 Windows 64 位操作系统上运行 Windows 32 位应用,并支持其他子系统,如 POSIX 和 OS/2。
这些子系统可以通过它们提供给在其上运行的应用的 API 来访问,当应用调用 API 时,它会被转换成适当的 Windows NT 系统调用,以便于执行所请求的操作。但是,随着时间的推移,这些最初的子系统被淘汰了,于是研究人员开始开发和扩展用于 Linux 的 Windows 子系统的功能。
导致 Linux 的 Windows 子系统的最初概念源于一个名为“Project Astoria”的项目,这是一个通用的 Windows 平台桥工具包,允许开发人员通过重用他们的 Android 代码或在 Windows 上运行原生 Android 应用来为手机构建 Windows 应用。这是通过允许 Android 应用在模拟环境中运行,只需进行最小的更改并访问微软平台 API 而实现的。但是,在 2016 年 2 月 25 日,微软正式宣布将停止“Astoria 项目”,并提出了这样一个论点,即这样一个仿真器对于原生的 Objective-C 工具链来说是多余的。后来,来自“Astoria 项目”和另一个名为“Project Drawbridge”的研究项目(这两个项目将在本章后面介绍)的见解和研究被开发成一个兼容性服务,称为 Linux 版本 1 的 Windows 子系统。微软在 2016 年发布了 Linux 的 Windows 子系统的初始版本,也称为 WSL1。
WSL 一览
用于 Linux 的 Windows 子系统是一种新的 Windows 操作系统兼容层功能,允许用户在 Windows 中本机运行 Linux 命令行工具、实用程序和未修改的 ELF64 二进制文件,而无需实际运行完整的 Linux 虚拟机。Linux 的 Windows 子系统是作为开发人员的工具开发的,但它在系统管理员和网络安全领域也有很高的采用率。
WSL 不仅仅是 Windows 上的一个 Linux“bash”shell;事实上,它是一个完整的兼容层,用于运行一个外观和行为都像 Linux 操作系统的环境。它使 Windows 用户能够运行常见的免费命令行软件,如“grep”、“sed”和“awk”或 Linux 发行版中的任何其他 ELF64 二进制文件,这些文件通常可以从微软商店免费下载。这意味着现在我们可以在 Windows 操作系统上使用具有类似 Linux 的用户体验的 Linux 工具,如 bash、vim 和 Emacs,而无需使用任何第三方 POSIX 兼容环境,如 Cygwin。
微软通过 WSL 的初始版本,也就是版本 1 或 wsl.exe,无疑已经拓展了操作系统研究的范围。现在,它不再是关于操作系统或站在 Windows 或 Linux 用户一边,而是基本上深入到为最终用户提供市场上最好的工具来解决他们的问题并构建应用,而不管底层平台如何。
WSL1 的优势
让我们假设您是 Windows 系统管理员或 Windows 开发人员,您正在浏览互联网上的一些如何设置 web 服务器之类的文章,突然,您在指令中看到一个美元符号($)提示 bash shell。这种内心独白马上就会开始:
- 哦,不!我不习惯这样;我的系统里没有这个。我可能必须启动一个虚拟机并在其上运行 Linux,然后才能按照 how-to 文章中的说明进行操作。但是那是很大的工作量!我不会这么做的。
这是成为 Linux 的 Windows 子系统起源的问题之一。更简单地说,有必要拥有一个子系统,它可以为开发人员和系统管理员提供无缝的能力,使他们能够立即在 Windows 上运行 bash 这样的 Linux 二进制文件。这可以消除在启动虚拟机和安装 Linux 操作系统以执行一些基本任务时所花费的担心、麻烦和时间。
以下要点进一步强调了 Windows Linux 子系统填补的空白和领域:
-
资源消耗–虚拟机为我们提供了很好的服务,并且不会有任何变化,但在内存、CPU 和存储方面肯定会有一些资源开销,而对于 Linux 的 Windows 子系统,底层主机操作系统上的资源消耗是最小的。老实说,如果我们有一个 bash shell 在 Linux 的 Windows 子系统中运行,那么仅仅为了检查几个 Linux 命令而启动一个虚拟机是没有任何意义的。
-
访问 Linux 工具–在 Windows 操作系统上运行 Linux 二进制文件,通过向 Windows 用户提供大多数强大的 Linux 应用和工具,为他们打开了一个全新的机会之窗。
-
跨平台开发–开发人员和系统管理员都可以利用 Linux 的 Windows 子系统来开发跨平台产品和工具,如。网芯。也就是说,我可以很容易地在 Windows 上测试一个项目,然后在 Linux 的 Windows 子系统中测试,甚至不需要启动 Linux 虚拟机。
-
为正确的工作提供正确的工具–我们的想法是使用最好的工具,而不考虑底层平台。这意味着,如果我愿意在 Linux 上部署 nginx web 服务器,那么我可以在 Windows 操作系统的一个子系统中这样做,这个子系统允许您像在 Linux 机器上运行一样运行 nginx。
-
相同的用户体验–WSL 提供的不仅仅是集成;它为 Linux 开发人员提供了无缝体验。大多数时候,开发人员甚至不会意识到他们不是在 Linux 操作系统上工作,而是在 Windows 操作系统之上运行原生 Linux 二进制文件的翻译层。
-
安全隔离–由于 WSL 是一个子系统,在其上运行的应用实际上是在一个安全、隔离的容器中运行,不会危及主机操作系统上的其他应用。
现在让我们来看看 WSL 的架构和一些内部组件,这些组件使它能够如此无缝地工作。
WSL1 的架构和组件
WSL 是由 Microsoft 实现的软件组件和驱动程序的集合,充当 Linux 用户空间和底层 Windows NT 内核之间的转换层,以转换系统调用、虚拟文件和文件系统。WSL 由用户模式和内核模式组件组成,这种从 Linux 用户空间到 Windows NT 内核的转换服务模拟了 Linux 内核,因此 Linux 应用甚至没有意识到它们不是在与 Linux 内核交互,而是在与 Windows NT 内核交互。让我们试着从图 1-1 来理解这一点。
图 1-1
WSL1 的架构
当“bash.exe”从主机 Windows 操作系统启动时,它会在一个 Linux 实例中启动一个 Linux 进程:/bin/bash,该进程保存一个数据结构来跟踪所有进程、线程和运行时状态。“LX 会话管理器服务”处理这种 Linux 实例的生命周期。该服务的作用是充当 Linux 子系统驱动程序的代理,并且该服务在安装和卸载的情况下也有帮助,以便同步操作,从而一次只允许一个进程执行这些操作。
2011 年,微软的一个研究团队启动了一个名为“ Drawbridge
”的项目,该项目后来引入了一个在 Windows 中实现的概念,即 PICO process。PICO 进程是一个基于进程的隔离容器,具有一个小的内核 API 表面,允许子系统在其中保存 Linux 二进制文件。当您在这些 Linux 二进制文件上执行任何操作时,容器或 PICO 进程结合 lxss.sys 和 lxcore.sys ,也称为 PICO provider 驱动程序,执行 Linux 系统调用到 NT APIs 的转换,以模拟 Linux 内核。简单地说,PICO 提供者向 Windows NT 内核发出等同于 Linux 系统调用的系统调用,反之亦然。
如图 1-2 所示,这些微微进程是普通主机进程的精简版本,具有隔离的地址空间,其中用户模式二进制【ntdll.dll】和没有映射,并且没有创建进程环境块(PEB)作为区分器,以便主机了解这些进程不是由主机主动管理的。主机仍然为这些进程提供底层操作系统支持,如线程调度、内存管理等。
图 1-2
NT 进程、最小进程和微微进程
内核模式驱动程序不包含任何来自 Linux 内核的代码,因此当从可执行文件发出 Linux 系统调用时,Windows NT 内核会将请求转发给 lxcore.sys ,后者会负责将 Linux 系统调用转换为等效的 Windows NT 调用。但是有一些 Linux 系统调用,比如 fork() ,在 Windows NT 中没有对应的调用。因此 lxcore.sys 必须使用内部 Windows NT 内核 API 复制并创建一个包含正确数据的新进程,以方便来自 Linux 的 Windows 子系统的任何此类请求。
WSL1 的缺点
就像任何软件或工具一样,Windows Subsystem for Linux version 1 也有局限性和缺点,我们将在下面的指针中讨论其中的一些。公平地说,WSL 是一个不断发展的产品,随着产品的不断发展,其中一些限制将会减轻:
-
Linux 是一个快速发展的开源操作系统,不时会有新的版本发布,但 WSL 中实现的翻译服务完全由微软管理,只要有新版本发布,他们就必须更新它。这在当前 Linux 版本的新特性中引入了延迟,直到微软继续前进并实现它们。
-
Windows NT 和 Linux 内核具有非常不同的文件系统、权限模型和内存管理,即使在 Windows 子系统中的最佳情况下,WSL 也不能将一些内容转换到 Windows NT 内核,因为在最坏的情况下,Windows 内核不支持这些内容。
-
WSL v1 不能运行所有的 Linux 软件,比如 32 位二进制文件,而且您可能会遇到不能在 WSL 上运行的软件,因为这些软件需要特定的 Linux 内核服务,而 Microsoft 尚未实现这些服务。以下是在 WSL 上运行和不运行的社区支持程序列表的链接:
https://github.com/ethanhs/WSL-Programs
。WSL2 通过在使用 Hyper-V 的轻量级实用虚拟机上运行 Linux 内核,解决了很多这样的问题。
Note
上述受支持和不受支持软件的列表由 Windows Subsystem for Linux 用户社区和独立贡献者维护,而不是由 Microsoft 维护。
- 用于 Linux 的 Windows 子系统通过使用 Xfce 和 xRDP 安装 Linux 桌面环境来支持图形用户界面(GUI)应用和完整的桌面体验,但是它仍然缺乏音频支持,并且提供较差的图形性能。如果在 WSL1 上继续进行任何积极的开发,这些问题可能会在 WSL1 的未来版本中得到解决。不仅如此,微软现在已经把所有的木头放在 WSL2 后面的一个箭头中,wsl 2 使用不同的方法针对相同的问题,并且许多这些问题将被自动修复。
Note
WSL2 仅在 Windows 10 版本 2004 (build 19041)上受支持,您必须加入“Windows Insider 计划”并选择“发布预览”环。这可能会在 5 月底或这本书发行的时候上市。
-
微软提出,Linux 的 Windows 子系统是为开发应用和增强开发人员的用户体验而设计的,而不是为桌面计算机和生产服务器而设计的,这排除了大量的用例和应用。
-
在 Microsoft Windows 中引入新的可执行文件格式,以及大量新的 Linux 应用,为终端软件安全供应商带来了巨大的挑战。2017 年,端点安全公司 Check Point 发表了一项研究,他们创造了 bashware (bash + malware)这个术语,它利用并利用 WSL 的底层机制在 Windows 上运行 ELF64 二进制文件。
这是之前引用的研究:
https://research.checkpoint.com/2017/beware-bashware-new-method-malware-bypass-security-solutions/
在这项研究中,研究人员试图证明他们可以使用 WSL 作为工具,从 Linux 子系统运行攻击 Windows 的恶意软件,但公平地说,微软已经在努力提供 WSL 上的防火墙和防病毒兼容性。
关键词和概念
在这一节中,我们将回顾组成 WSL 的一些关键术语和重要概念。表 1-1 提供了一些我们将在本书接下来的章节中使用的缩写。
表 1-1
重要缩写
|缩写
|
膨胀
|
| --- | --- |
| 西北地区(Northwest Territories) | 新技术 |
| 发行版本 | 分发包 |
| 旧历法 | 操作系统 |
| 伏特计 | 虚拟计算机 |
| WSL | 面向 Linux 的视窗子系统 |
| 极低频 | 可执行文件和链接格式 |
| 体育课 | 可移植可执行文件 |
| 应用接口 | 应用界面 |
| 戊巴比妥 | 过程环境块 |
现在,我们将快速浏览一些基本的关键字、概念和定义,以帮助您理解 Linux 的 Windows 子系统,并在开始学习之前为您打下一些基础。如果你不是一个 Linux 用户,你可能不熟悉其中的一些概念,并且来自 Windows 端,这些将加速你的学习。
发行版本
Distro 是 Linux 发行版的缩写,它只是一个由开源软件包、工具和库组成的操作系统。Linux 用户基本上可以从网上各种各样的发行版中下载并安装他们选择的 Linux 发行版,这就是他们获得操作系统的方式。WSL 的 Linux 发行版既可以从微软商店下载,也可以手动下载,这一点我们将在本书后面介绍。这些发行版由合作伙伴提供,而不是由微软提供。虽然现在有超过 500 个 Linux 发行版可用,其中大多数也在积极开发中,但也有一些商业发行版,如 Fedora、openSUSE 和 Ubuntu。Ubuntu 实际上是最流行的桌面 Linux 发行版之一。此外,一些 Linux 发行版完全是社区驱动的,比如 Debian、Slackware、Gentoo 和 Arch Linux。
子系统
从一开始,Windows NT 就允许子系统(如 Win32 子系统)与 NT 内核共存。在操作系统的上下文中,子系统是大型软件中的自包含系统,就像操作系统一样。
在 Windows NT 中,这些子系统充当用户模式应用和操作系统内核功能之间的接口,并且存在多个子系统,实现完全不同的 API 集来支持为许多不同类型的操作系统编写的应用。在 Windows 10 操作系统上,只有可以运行 32 位 Windows 应用的 Win32 子系统存在,而 OS/2 子系统和 POSIX 子系统不再存在,并且已经停止使用。
核心
现代操作系统构建成多层,内核是操作系统的核心组件,如图 1-3 所示。内核之所以如此命名,是因为就像硬壳中的种子一样,Linux 内核作为核心组件存在于 Linux 操作系统中。内核主要充当用户应用和硬件之间的接口。
图 1-3
内核是操作系统最里面的层/环
在图 1-3 中,最外面的“绿色”环代表最低特权;这意味着环 3 中的应用最不可信,需要更高的特权来执行关键操作,而内核是最里面的环,用“红色”表示特权最高或最可信,即环 0。
这样做的主要目的是促进硬件-软件通信,并执行其他低级操作,如
-
进程管理
-
中断处理
-
内存管理
-
设备管理
-
输入输出通信
-
文件系统
当计算机系统启动时,引导程序首先将内核加载到主内存中。拥有一个小的内核是很重要的,因为它驻留在内存中执行前面提到的基本服务,并且它应该在内存中以保护模式运行,这样它就不会被其他正在运行的程序覆盖,这可能是灾难性的。
核心态
简而言之,在内核模式下运行的程序或指令可以完全且不受限制地访问底层硬件。一般来说,内核模式是为操作系统的低级、最关键的功能保留的,在这种情况下,任何崩溃都可能是灾难性的,并且可能会破坏整个系统。所有用户进程都将在用户模式下执行,直到它们得到一个系统调用。任何系统调用都在内核模式下执行,内核模式下会生成一个系统陷阱,并且模式位被设置为零(0)。一旦执行完成,就会生成另一个系统陷阱,将模式位设置为一(1)。图 1-4 显示了内核态和用户态的关系。
图 1-4
用户模式和内核模式
用户状态
计算机系统上运行的大多数程序和代码都以用户模式执行,用户模式不能直接访问系统硬件,只能通过系统 API 访问资源。这种隔离是通过设计并使用保护环来保护的,保护环是计算机系统架构中两个或多个分级权限级别之一。这样,由于权限级别的限制,用户模式(通常是最外面的保护环)中的任何崩溃都不会影响系统上的任何其他东西,并且这种崩溃总是可恢复的。整个目的是防止用户程序意外地用用户数据覆盖关键的操作系统文件,或者防止不止一个进程试图写或操作相同的文件而以灾难性的失败告终。
系统调用
简单来说,系统调用或 syscall 是内核提供的服务,可以从用户模式程序中调用,以与底层操作系统进行交互。就计算而言,系统调用是计算机程序通过 API(应用接口)以编程方式从运行它的操作系统内核请求服务的一种方式。系统调用是内核系统访问系统资源的入口点,比如内存、进程、文件访问等等。
表 1-2 提供了一些 Windows 和 Unix 系统调用,只是为了让您了解系统调用提供的服务种类以及可用的类型。
表 1-2
用于翻译的 Windows 和 Unix 系统调用映射
|种类
|
Windows 系统调用
|
Unix 系统调用
|
| --- | --- | --- |
| 进程管理 | CreateProcess() | 叉子( ) |
| | ExitProcess() | 退出( ) |
| | WaitForSingleObject() | 等待( ) |
| 文件处理 | CreateFile() | 打开( ) |
| | 读取文件() | 阅读( ) |
| | WriteFile() | 写( ) |
| | CloseHandle() | 关闭( ) |
| 设备操纵 | SetConsoleMode() | ioctl() |
| | ReadConsole() | 阅读( ) |
| | WriteConsole() | 写( ) |
| 沟通 | CreatePipe() | 管道( ) |
| | CreateFileMapping() | shmget() |
| | MapViewOfFile() | mmap() |
| 进入和保护 | SetFileSecurity() | chmod() |
| | InitlializeSecurityDescriptor() | umask() |
| | SetSecurityDescriptorGroup() | 乔恩() |
| 多方面的 | GetCurrentProcessID() | getpid() |
| | 设置计时器( ) | 警报( ) |
| | 睡眠( ) | 睡眠( ) |
Windows NT 内核
装有微软视窗操作系统的计算机系统由视窗内核组成,也称为视窗 NT 内核。Windows NT 的早期版本被开发成两种变体,第一种用于工作站,第二种用于服务器计算机。它是基于 MS-DOS 的继任者,后来发展成为我们今天使用的 Windows 10 操作系统。
Windows 操作系统架构由组件组成,大致分为用户模式和内核模式:
-
硬件抽象层(HAL ),它是一个软件层,充当底层硬件和操作系统高层之间的接口
-
Windows 内核
-
内核模式驱动程序
-
用于以下目的的内核模式执行服务:
-
对象管理
-
内存管理
-
进程和线程管理
-
输入/输出管理
-
在内核模式下运行的配置管理驱动程序和其他支持服务
-
-
用户模式驱动程序
-
用户模式环境子系统
Note
大多数驱动程序在用户模式下运行以获得稳定性,但仍有一些例外,如视频驱动程序在用户和内核模式下都被分段以提高性能,这在 Windows Vista 性能问题引起强烈抗议后再次改变。在哪里保存这些驱动程序仍然没有明确的界限,这是一个讨论和实验的问题。
Linux 内核
Linux 内核是 Linux 操作系统的核心组件,充当系统硬件及其进程之间的接口。它受欢迎的主要原因之一是它是免费和开放源码的,这吸引了来自世界各地的贡献者。Windows NT 内核和 Linux 内核的主要区别在于,Windows 内核附带了一个商业软件(操作系统),而 Linux 内核是开源的,可以免费下载。
一旦 Linux 版本 2 的 Windows 子系统(WSL2)正式推出,微软将开始提供一个完整的 Linux 内核和 Windows 操作系统,该操作系统将完全由微软管理,并通过 Windows updates 进行更新。
极低频
ELF 代表可执行和链接格式,它是可执行文件、目标代码、共享库和核心转储的通用标准文件格式。ELF 被设计成灵活、可扩展和跨平台的,这意味着它不局限于特定的处理器、指令集或硬件架构。这使得 ELF 格式被许多不同硬件平台上的不同操作系统所采用。
使用 ELF 文件格式的可执行文件由 ELF 文件头和文件数据组成,文件数据包括
-
程序头表–列出 0 个或多个内存段;这些内存段包含文件运行时执行所需的信息。
-
章节标题表–列出 0 个或多个章节;其中包含用于链接和重定位的重要数据。
-
文件数据–程序头或段头表中引用的数据。
微微过程
在隔离环境中运行应用的传统使用案例中,我们使用安装了特定操作系统的虚拟机来将应用与任何底层主机操作系统的依赖性分离。这种方法对我们很有效,并且已经达到了目的,它为独立于底层操作系统的应用提供了安全隔离,同时允许兼容性和执行连续性,这使我们甚至能够将应用迁移到其他操作系统或计算机上。
尽管有这些优势,虚拟机在磁盘、内存、CPU 等方面有很大的资源开销。因此,微软开始研究一个名为 Drawbridge
的项目,目的是开发一种新的计算方式,目标是实现一种轻量级方法来在隔离环境中运行应用,使应用的操作系统依赖性与底层主机操作系统分离。Project Drawbridge 结合了两项核心技术:
-
微微工艺–P基于工艺的IsolationCOntainer
-
库操作系统–应用工作负载的目标操作系统,独立于底层操作系统运行。这就是 WSL 分发包发挥作用的地方,它使 Linux 的 Windows 子系统能够工作。
PICO 进程旨在限制底层操作系统管理该进程内的用户模式地址空间,它只是普通主机进程的较小版本,与内核模式驱动程序一起工作,充当主机操作系统内核和用户模式库操作系统之间的代理。
为了阻止底层操作系统管理这些微微进程,这些进程被标记为一个最小进程,它告诉主机的其余部分不要管理这些进程。与传统的 NT 进程不同,当生成一个最小化的进程时,不会创建线程在该进程中运行,用户模式的地址空间也不会改变。更简单地说,PICO 进程是与内核模式驱动程序相关联的最小进程。
摘要
在前面的小节中,我们学习了 Linux 的 Windows 子系统的架构概述和组件,以及它的优缺点。我们还研究了一些与 Windows 和 Linux 操作系统相关的重要关键词和概念,以及一些核心思想和概念,如 PICO process,这将有助于您理解 WSL 的内部工作方式。
在下一章,我们将学习在 Windows 10 操作系统上安装和设置 WSL。
二、下载、安装和设置
适用于 Linux 的 Windows 子系统是一项兼容性功能,它充当转换层,但在使用之前必须启用。然后我们需要从微软商店安装一个 Linux 发行版,最后在第一次使用之前进行设置。让我们一个接一个地开始这些步骤。
启用 WSL 功能
Linux 的 Windows 子系统需要在主机操作系统级别启用,有两种方法可以实现这一点:第一种是使用图形用户界面(GUI ),第二种是使用 PowerShell。除非您启用 Windows Subsystem for Linux 特性,否则您无法在您的系统上运行 WSL,并且您将收到如图 2-1 所示的以下错误。这个图像是在我的系统上安装 Linux 发行版时捕获的,没有启用 WSL 特性,因此出现了错误。
表 2-1
Linux 发行版和直接下载 URL
|分发名称
|
下载 URL
|
| --- | --- |
| Ubuntu 18.04 | https://aka.ms/wsl-ubuntu-1804
|
| Ubuntu 18.04 ARM | https://aka.ms/wsl-ubuntu-1804-arm
|
| Ubuntu 16.04 | https://aka.ms/wsl-ubuntu-1604
|
| Debian GNU/Linux | https://aka.ms/wsl-debian-gnulinux
|
| Kali Linux | https://aka.ms/wsl-kali-linux
|
| OpenSUSE Leap 42 | https://aka.ms/wsl-opensuse-42
|
| SUSE Linux 企业版 12 | https://aka.ms/wsl-sles-12
|
| WSL 的 Fedora 混音 | https://github.com/WhitewaterFoundry/WSLFedoraRemix/releases/
|
图 2-1
WSL 功能未启用
让我们从第一种方法开始。
GUI 方法
要从 GUI 启用 WSL,请按照下列步骤操作:
图 2-2
启动“程序和功能”
-
按 Windows + R 键启动运行对话框。
-
现在键入 appwiz.cpl 并点击 Enter 按钮或点击 OK,如图 2-2 所示。
图 2-3
选择“打开或关闭 Windows 功能”
- 这将弹出“程序和功能”窗口,您必须从左上角选择“打开或关闭 Windows 功能”,如图 2-3 所示。
图 2-4
单击“用于 Linux 的 Windows 子系统”功能复选框
-
一个新的“Windows 功能”窗口将在您的屏幕上弹出。请向下滚动并左键选中“Windows Subsystem for Linux”旁边的复选框(图 2-4 )。
-
这将启用 Windows 功能,但仍需要重新启动系统才能看到配置和更改生效。一旦系统重新启动,您现在可以运行 WSL,而不会看到任何错误,如图 2-1 所示。
现在让我们看看使用 PowerShell 的第二种方法。
PowerShell 方法
使用 PowerShell 为 Linux 启用 Windows 子系统是一个简单的过程:
- 运行以下 cmdlet 可能是最简单的方法:
图 2-5
按“Y”确认启用该功能
- 一旦你运行它,它会提示重启你的系统,如图 2-5 所示。按“Y”并按回车键启用 Windows 功能。
Enable-WindowsOptionalFeature -Online -FeatureName
Microsoft-Windows-Subsystem-Linux
下载并安装 Linux 发行版
在启用 Windows 特性来支持 Linux 的 Windows 子系统之后,您必须安装一个来自微软合作伙伴的 Linux 发行包,比如 Ubuntu、Debian、Kali Linux 等等,以运行 WSL 的一个实例。有多种方法可以下载分发包(distros),下面列出了一些方法以及您需要执行的具体步骤。
从 Microsoft 商店下载
Linux 发行版可以在以下说明的帮助下直接从微软商店下载:
图 2-6
搜索发行版并单击它
-
点击开始菜单,搜索“微软商店”。然后点击它启动微软商店。
-
在右上角,有一个搜索框(步骤 1);键入“Linux”并按回车键。您将在搜索结果中看到一些 Linux 发行包。
-
仅仅为了举例,我们将从微软商店下载 Ubuntu 18.04 LTS(发行版),点击它(步骤 2),如图 2-6 所示。
图 2-7
点击“安装”按钮
- 这将打开发行版页面,您会发现右上角有一个“安装”按钮,如图 2-7 所示,一旦您单击此按钮,它将开始在您的系统上安装发行版,它将作为 Windows 上的一个应用提供。
手动下载发行版
微软已经创建了直接链接,通过 https://aka.ms/
风格的短 URL 下载大量流行的 Linux 发行版,如表 2-1 所列。这意味着您可以访问其中一个 URL 并下载 Linux 发行版,如果您的系统通过组策略禁用/阻止了 Microsoft Store,这种方法会非常有用。
下载完成后,请双击应用包(*。appx)文件来安装 Linux 发行版,如图 2-8 所示。
图 2-8
安装发行版应用包(*。appx)下载后
使用 PowerShell 下载
使用 PowerShell,使用Invoke-WebRequest
cmdlet 并将直接下载 URL 作为参数传递给“-URI”参数,可以很容易地下载 WSL 分发包。清单 2-1 中的 PowerShell 代码演示了如何下载 Ubuntu 18.04 应用包。类似地,前面提到的其他 URL 也可以用来下载 WSL 的各种发行版。可以通过更改进度偏好变量$ProgressPreference = 'SilentlyContinue'
来静音进度条;这将更快地下载软件包,而不会在您的控制台上弹出任何进度条,在 PowerShell v5.1 和更低版本中,这可以提高下载速度。
使用管理权限启动 PowerShell 控制台,复制粘贴以下代码片段,然后按 Enter 键执行它。
$URL = 'https://aka.ms/wsl-ubuntu-1804'
$Filename = "$(Split-Path $URL -Leaf).appx"
$ProgressPreference = 'SilentlyContinue'
# starts download from the URL
$Params = @{
URI = $URL
OutFile = $Filename
UseBasicParsing = $true
}
Invoke-WebRequest @Params
# invoking the application package
# to start the installation
Invoke-Item $FileName
Listing 2-1Downloading Linux (Ubuntu 18.04) distribution using PowerShell
运行这段代码将下载 Ubuntu 18.04 LTS 应用作为一个文件:wsl-ubuntu-1804.appx
。下载完成后,您可以在。appx 文件在当前工作目录下运行应用安装 GUI,然后点击下一步安装如图 2-9 所示。
图 2-9
单击“下一步”开始安装发行版
或者,可以使用 PowerShell cmdlet Add-AppxPackage
添加每个应用包(* .appx)到用户帐户(列表 2-2 )。
$URLs = @(
"https://aka.ms/wsl-ubuntu-1804",
"https://aka.ms/wsl-ubuntu-1804-arm",
"https://aka.ms/wsl-ubuntu-1604",
"https://aka.ms/wsl-debian-gnulinux",
"https://aka.ms/wsl-kali-linux",
"https://aka.ms/wsl-opensuse-42",
"https://aka.ms/wsl-sles-12"
)
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'
Foreach($URL in $URLs){
$Filename = "$(Split-Path $URL -Leaf).appx"
Write-Host "Downloading: $Filename" -Foreground Yellow -NoNewline
try{
$params = @{
Uri = $URL
Outfile = $Filename
UseBasicParsing = $true
}
Invoke-WebRequest @params
Add-AppxPackage -Path $Filename
if($?){
Write-Host " Done" -Foreground Green
}
}
catch{
Write-Host " Failed" -Foreground Red
}
}
Listing 2-2Adding all Linux distribution packages to user account
如果执行 PowerShell 代码,它将一个接一个地安装所有的 Linux 发行版,如图 2-10 所示,您也可以通过进入开始菜单并检查最近添加的应用来验证这一点。
图 2-10
Linux 发行版将出现在开始菜单中
使用 curl.exe 下载
发音为“curl”是一个非常流行的开源命令行工具,用于执行 web 请求和从命令行传输数据。curl.exe
可以与 URL 一起使用,将 WSL 分发包下载到本地机器:
curl.exe -L -o wsl-kali-linux.appx https://aka.ms/wsl-kali-linux
图 2-11 展示了一旦我们用一个指向 Linux 发行包的直接 URL 运行curl.exe,它将下载这个包并保存在本地路径上,这个路径被传递了一个参数给“-o”参数,就像我们例子中的wsl-kali-linux.appx
;如果需要,可以定制这个输出文件名,输出将被写入一个新文件。当您在 bash 脚本中使用 WSL 的下载和设置时,使用curl.exe
是有益的,在这种情况下,我们在前面小节中使用的 PowerShell cmdlets 将不起作用。
图 2-11
使用 curl 下载 Linux 发行包
Note
我们运行的是 curl.exe,而不是 curl,因为在 PowerShell 中,curl 也是 Invoke-WebRequest cmdlet 的别名,这完全是两码事。
设置和配置 WSL
在上一节中,我们学习了在我们的系统上下载和安装 Linux 的 Windows 子系统的各种方法。下一件事是学习如何为第一次使用准备和配置 WSL,但是在此之前,让我们研究一下在 Linux 的 Windows 子系统中运行 Linux 发行版的各种方法。
启动发行版
Linux 发行版可以作为已安装的应用启动,或者通过运行特定于 Linux 发行版的可执行文件,甚至使用wsl.exe来启动。让我们一次研究一种方法。
使用应用
因此,首先,进入开始菜单,键入发行版的名称,如“Ubuntu”,如图 2-12 所示。
图 2-12
转到开始菜单,搜索 Linux 发行版的名称
现在,双击 Ubuntu 应用,如图 2-12 中突出显示的应用,首次启动 Linux 的 Windows 子系统。它会提示您等待几分钟,准备并初始化第一次使用的发行版。
使用 wsl.exe
WSL 发行版也可以通过wsl.exe
启动;如果您不带任何参数运行这个可执行文件,那么它将启动默认的分发包,如图 2-13 所示。
图 2-14
使用 wsl.exe 启动特定的 Linux 发行版
图 2-13
使用 wsl.exe 启动默认的 Linux 发行版
要列出安装在您系统上的所有分发包并确定默认的分发包,请运行带有--list
或–l
的wsl
可执行文件:
wsl.exe –list
wsl.exe –l
通常需要运行一个特定的分发包;在这样的场景中,我们可以利用图 2-14 中所示的--distribution
或-d
参数和 wsl.exe,并将发行版的名称作为参数传递,如清单 2-3 所示。
C:\>wsl.exe –l
Windows Subsystem for Linux Distributions:
Ubuntu-18.04 (Default)
openSUSE-42
SLES-12
kali-linux
C:\>wsl.exe --distribution kali-linux
C:\>wsl.exe -d sles-12
Listing 2-3Running a specific Linux distribution
我们将在本书后面详细研究wsl.exe
接受的其他功能和命令行参数;现在,让我们来理解一些关于像这样使用wsl.exe
调用 Linux 发行版的要点:
-
WSL 在 CMD 或 PowerShell 提示符下的当前工作目录中启动发行版。
-
通过wsl.exe调用的 Linux 发行版将作为该发行版的默认用户运行,但是您可以使用–用户或 -u 参数通过传递特定用户的名称作为参数来改变该行为:
-
通过wsl.exe调用的 Linux 发行版将拥有与调用进程和终端相同的 Windows 管理权限。
wsl.exe --distribution Ubuntu-18.04 --user prateek
使用可执行文件
如图 2-15 所示,所有的 Linux 发行版都可以使用它们各自的可执行文件轻松地直接启动,这些文件都放在文件夹“C:\ Users *{用户名}**\ AppData \ Local \ Microsoft \ windows apps *”中,下面是清单 2-4 中的几个例子,您可以自己尝试一下。
图 2-15
使用可执行文件启动发行版
# launching ubuntu 18.04
ubuntu1804.exe
# launching kali linux
kali.exe
# launching openSUSE 42
openSUSE-42.exe
Listing 2-4Running a Linux distribution through its executable
在这一小节中,我们学习了在 WSL 中运行 Linux 发行版的各种方法,但是当第一次调用 Linux 发行版时,第一个设置会提示用户创建一个用户帐户;让我们深入了解一下,并学习如何在 WSL 中管理用户帐户。
设置和管理用户帐户
创建用户是在 WSL 上设置新的 Linux 发行版的第一步,所以一旦初始化完成,如图 2-16 所示,它将提示您创建一个带有密码的新用户帐户。该用户帐户被自动配置为发行版的默认用户,并作为 Linux 管理员添加到“ sudo ”组中。每次安装、重新安装或重置发行版时,都需要用户配置。
图 2-16
发行版初始化期间的用户帐户设置
Note
当输入密码时,出于安全原因,它不会回显到控制台,这并不意味着系统没有接收到击键。
默认情况下,启动发行版时不需要密码,但是当您使用“ sudo ”命令提升任何进程的权限时,将需要密码。
要在 Linux 中更改您当前的用户密码,请打开您的 Linux 发行版(如 Ubuntu)并输入命令passwd
,如图 2-17 所示,系统会提示您输入您当前的密码,一旦您提供了密码,它会再次要求确认。
图 2-17
重置密码
如果您忘记了任何特定 Linux 发行版的密码,请从“开始”菜单打开 PowerShell 或“命令提示符”,并使用以下命令在目标 WSL 发行版上以 root 用户身份运行它:
wsl -u root -d <name of distribution>
一旦您的 WSL 发行版以 root 用户身份运行,继续使用passwd
命令和您想要重置密码的用户名,如下例所示:
passwd prateek
如果您不使用 root 用户,您将没有足够的权限为任何其他用户重置密码,而不输入他们的当前密码,这是我们首先忘记的。
权限模型
Linux 的 Windows 子系统中的 Unix 用户是独立于 Windows 权限模型的非 Windows 用户帐户,在您的 Linux 发行版中提升权限将需要该权限模型。在 Linux 和 Windows 的 WSL 中有两个独立的权限模型,它们是相互独立的。这意味着 Linux 管理员用户在 Linux 环境中只有提升的特权,而 Linux 中的权限在 Windows 中不起作用。
问题是,由于 WSL 是由 Windows 用户帐户启动和初始化的,因此该 Windows 用户帐户可以访问的任何 Windows 资源也可以从 Linux 的 Windows 子系统内部访问。
如图 2-18 所示,我们可以很容易地访问 Linux 环境中的挂载点,这些挂载点只不过是安装在 Linux 的 Windows 子系统上的 Windows 驱动器。当当前 Windows 用户在他们可以访问的目录上运行“ls”命令,然后通过管道将结果传递给“wc -l”命令以获取返回的行数时,我们观察到计数大于零,但是如果当前用户试图访问他们没有适当权限的任何其他目录,则不会返回任何结果。这证明了前面的观点,即使您在 Linux 子系统中工作,Windows 权限也应用于您正在访问的 Windows 资源。
图 2-18
权限模型限制
但是当我试图访问一个我没有权限访问的 Windows 目录时,它失败了,并显示“权限被拒绝”错误。这是因为启动 WSL 的 Windows 用户" Prateek "可以访问它的用户配置文件文件夹 C:\Users\Prateek。THINKPAD ,但是对“管理员”的用户配置文件文件夹没有权限。
更新和升级发行版
现在我们知道了如何安装 WSL 并为第一次使用而初始化它,但是即使您进行了全新的安装,很有可能您的 Linux 发行版附带的一些默认包和工具已经有点过时了,并且存在新的版本。因此,我们需要一种机制来将它们更新到最新版本,因为这些版本是最稳定的,并且会有错误修复和安全改进。
Note
为了简化读者,我们假设您使用的是 Ubuntu 或 Debian Linux 发行版,这是两个最流行的发行版。如果您正在使用任何其他 Linux 发行版,那么以下更新/升级命令可能不适用于您。
首先,在进入如何做之前,让我们先了解更新和升级之间的一般区别。升级是用更新更好的产品版本替换当前产品的行为,而更新则是修改您当前的产品。在 Linux 术语中,更具体地说是对 Ubuntu 和 Debian 而言,“更新”意味着刷新已安装软件包的列表,比如增加版本等等,而不修改任何其他内容,“升级”意味着安装已安装软件包列表的任何更新。
几乎所有的发行版都是轻量级的最小软件包,可以快速下载和初始化;他们只有附带的必要工具和库。使用清单 2-5 中的命令更新和升级您的发行版是一个好主意;请注意,这一步可能需要一段时间才能完成,你会看到如图 2-19 所示的包正在被下载。
图 2-19
更新/升级 WSL 发行版
sudo apt update && sudo apt upgrade
Listing 2-5Updating and upgrading the Windows Subsystem for Linux
在图 2-19 中,apt
代表“高级包工具”,而apt
是一个命令行工具,帮助处理 Ubuntu、Debian 和相关 Linux 发行版上的包。apt
与 Ubuntu 和 Debian 打包系统交互,寻找和安装新的软件包,升级或删除软件包。但是有一个普遍的误解,认为apt
update 是在 Linux 上安装软件包的新版本更新,事实并非如此。相反,它会更新名为 apt 包索引的数据库,该数据库在' /etc/apt/sources.list '文件中保存了发行版软件库中可用包的列表。
例如,如果你安装了 Python v3.5 版,那么在 apt 更新之后,前面提到的数据库将会知道 Python 的一个更新版本,3.6 版,并且是可用的。现在当你运行apt upgrade
时,它会将 Python v3.5 升级到更新的版本。
但是故事并没有到此结束,作为一名开发人员,出于各种原因,您仍然需要在您的 Linux 发行版中使用其他工具和包;因此,在下一小节中,我们将研究在 Linux 的 Windows 子系统上安装额外的软件。
安装附加工具和软件包
为 Linux 提供 Windows 子系统的真正目的是让开发人员能够在 Windows 中使用他们喜欢的 Linux 工具,以增强他们的整体开发体验。就像任何风格的 Linux 操作系统一样,在 Linux 的 Windows 子系统上,这些 Linux 实用程序、工具和包中的大部分都可以使用像apt
这样的包管理器轻松安装,它是管理包的工具的集合。在下面的例子中,我们使用apt install
命令在我们的 Linux 发行版上安装nodejs
、git
和nmap
:
sudo apt install nodejs git nmap
APT 是像apt
、apt-get
和apt-cache
这样的工具的集合,它带来了更多的功能,例如通过指定搜索关键字使用 apt-cache search 搜索包的能力,它甚至可以使用 apt-cache show 命令检查包的详细信息,如架构、大小、MD5 校验和等,如图 2-20 所示:
图 2-20
使用 apt 搜索和安装软件包
apt-cache search aws-cli
apt-cache show python3-botocore
摘要
在本章中,我们学习了如何在 Windows 10 系统上为 Linux 启用 Windows 子系统,以及下载和安装 Linux 发行版的各种方法。完成之后,我们首次推出了 Linux 的 Windows 子系统,接下来是设置、配置和用户管理。在下一章中,我们将学习在 Windows 和 Linux 环境之间构建混合体验,弥合两个操作系统之间的差距,并为开发人员和系统管理员提供两个世界的精华。
三、构建混合体验
用于 Linux 的 Windows 子系统最强大的用例是在 Windows 和 Linux 操作系统之间构建混合体验的能力,它们是如此无缝,以至于感觉根本没有摩擦。毕竟,整个想法是通过提供工具和配置来弥合两个操作系统之间的差距,从而精挑细选两个世界的精华。
在本章中,我们将介绍 WSL 的启动配置,以自动挂载 Windows 文件系统,在主机文件中设置条目,并从 WSL 运行 Windows 进程和可执行文件。在本章的后面,我们还将介绍如何将 Windows 路径转换为 Linux 路径,反之亦然,最后我们将了解共享环境变量。
让我们从 Linux 的 Windows 子系统的启动配置开始。
WSL 启动配置–wsl.conf
wsl 允许您使用位于/etc/wsl.conf 的文件为所有分发包独立设置启动配置,并且每当 WSL 启动时,配置都会自动应用。此配置文件遵循 INI 文件格式,这是软件配置文件的标准文件格式,其基本结构由保存在文本文件中的[节]、属性和值(键=值对)组成。默认情况下不会创建这个文件,如果您的 WSL 环境中不存在这个文件,您也可以自己创建一个。
Linux 的 Windows 子系统将在启动时检测并解析该文件,以获取配置设置,这些设置分为以下三个部分:
-
[自动装载]
-
[网络]
-
[互操作]
我们将首先从[automount]部分开始,并通过一些例子来更好地理解这一点。
[自动装载]部分
顾名思义,这个部分控制如何在启动时自动挂载 Linux 发行版中的各种文件系统。这些设置可以控制 Windows 文件系统固定驱动器在 WSL 上的安装方式和位置。
表 3-1 提供了本节中允许的属性及其各自值的列表。
表 3-1
[automount]部分下的可选属性列表
|财产
|
价值
|
默认
|
描述
|
| --- | --- | --- | --- |
| 使能够 | 布尔 | 真实的 | 当设置为 true 时,自动挂载固定驱动器,如 C:\或 D:\和目录/mnt 下的 drvfs。 |
| mountFsTab | 布尔型 | 真实的 | 设置为 true 时,会自动挂载在/etc/fstab 文件中声明的其他文件系统,如 SMB 共享。 |
| 根 | 线 | /mnt/ | 指定固定驱动器的默认安装位置;这意味着如果我们将/test/声明为 root 属性值,那么我的固定驱动器将被挂载为/test/c、/test/d 等等。 |
| 选择 | 逗号分隔列表 | 空字符串 | 该值被附加到默认的 drvfs 挂载选项字符串中。 |
默认情况下,WSL 将您的 Windows 文件系统驱动器挂载在 Linux 发行版的/mnt/
文件夹中,比如使用名为drvfs
的 WSL 文件系统插件将/mnt/c/
挂载到 C:\驱动器,将/mnt/d/
挂载到 D:\驱动器。我们将在本书的后面深入探讨drvfs
和文件系统。现在,让我们假设我们想将带有drvfs
的固定驱动器挂载到一个文件夹而不是/mnt/
文件夹,然后我们可以在[automount]部分的root
属性下将其定义为一个值。
如图 3-1 所示,一旦我们将/etc/wsl.conf
文件中root
属性下的/test/ folder 配置为挂载 Windows 硬盘的默认文件夹,并重启 WSL,那么它会自动挂载固定硬盘;在我的例子中,C:\和 D:\驱动器位于 Linux 发行版下一次发布时的/test/文件夹中。
图 3-1
安装 Windows 驱动器的根文件夹
Note
要使更改生效,您必须在 Windows 上重新启动 LxssManager 服务,或者终止并重新启动 Linux 的 Windows 子系统。除非您这样做,否则您可能看不到根文件夹上装载的 Windows 驱动器。
现在,如果我在我的 WSL 上检查已挂载的驱动器,并且只选择带有关键字drvfs
的驱动器,如图 3-2 所示,那么它将显示通过wsl.conf
文件的[automount]部分挂载的驱动器。我们在示例中使用的grep
命令过滤/搜索特定的字符模式(在我们的例子中是drvfs
,并显示包含该模式的mount
命令的所有输出行。
图 3-2
验证驱动器和文件系统
在这一小节下还有另一个称为options
的属性,它会自动将值附加到drvfs
挂载选项,这是一种在没有 Linux 元数据的情况下控制 Windows 文件权限的方法。该属性下的装载选项可以包括以下项目:
-
uid–所有文件的所有者使用的用户 id
-
Gid–所有文件的所有者使用的组 ID
-
umask–排除所有文件和目录的八进制权限掩码
-
fmask–排除所有常规文件的八进制权限掩码
-
dmask–排除所有目录的八进制权限掩码
如图 3-3 所示,一旦我们在 wsl.conf 文件中配置了这个属性并重启了我们的 wsl 发行版,它就会将我们提供的挂载选项添加到挂载的文件夹中。
图 3-3
通过 wsl.conf 文件设置 drvfs 挂载选项
现在让我们看一下[network]部分,了解我们如何利用它在 WSL 环境中设置 DNS 条目和主机到 IP 地址的映射。
[网络]部分
WSL 配置文件的[network]部分提供了表 3-2 中列出的两个重要属性,它们可用于调整和控制域名解析以及在 Linux 的 Windows 子系统上配置主机文件(主机到 IP 地址映射)的方式。
表 3-3
[interop]部分下的可选属性列表
|财产
|
价值
|
默认
|
描述
|
| --- | --- | --- | --- |
| enabled
| 布尔型 | 真实的 | 当设置为真时,WSL 发行版将像 notepad.exe 一样启动 Windows 进程;否则,此功能将被禁用。 |
| appendWindowsPath
| 布尔 | 真实的 | 当设置为 True 时,WSL 会将 Windows 路径附加到发行版的环境变量$PATH 中。 |
表 3-2
[网络]部分下的可选属性列表
|财产
|
价值
|
默认
|
描述
|
| --- | --- | --- | --- |
| 发电主机 | 布尔 | 真实的 | 如果设置为 true,WSL 将从 Windows hosts 文件中自动生成具有主机到 IP 地址映射的/etc/hosts:% WINDIR % \ System32 \ drivers \ etc \ hosts。 |
| generateResolvConf | 布尔 | 真实的 | 如果设置为 true,WSL 会自动生成/etc/resolv.conf 文件,其中包含用于 WSL 中名称解析的域名服务器列表。 |
[network]子部分下的第一个属性是generateHosts
,该属性的目的是基于 Windows hosts 文件:% WINDIR % \ System32 \ drivers \ etc \ hosts,使用主机到 IP 地址的映射在 WSL 上自动生成 hosts 文件:/etc/hosts。
图 3-4 显示一旦我删除了 WSL 上的主机文件并重启它,然后如果在/etc/wsl/conf
文件中generateHosts
属性被设置为true
,它将根据 Windows 主机文件自动重新生成主机文件。
图 3-4
从 Windows 主机文件自动生成/etc/hosts 文件
表 3-4
输出类型选项列表
|参数
|
描述
|
| --- | --- |
| [构成动植物的古名或拉丁化的现代名] | 将 Windows 打印为 Unix 绝对路径格式 |
| -w | 打印 Unix 路径的 Windows 窗体 |
| -m | 打印 Unix 路径的 Windows 格式,但带有正斜杠/ |
| -你 | 打印 Windows 路径的 Unix 格式;是默认参数 |
这一小节下的第二个属性是generateResolvConf
,当设置为true
时,它会创建一个域名服务器列表,供 Linux 的 Windows 子系统使用。在下面的例子中,如图 3-5 的步骤 1 所示,我已经通过在wsl.conf
文件中将generateResolvConf
属性设置为false
来禁用它。现在,如果我尝试 ping 任何网站(步骤 2),它无法将任何主机名解析为它们各自的 IP 地址,因为没有名称服务器来帮助解析名称。让我们像步骤 3 一样返回并再次恢复设置,并终止我的 WSL 发行版(步骤 4)以使配置更改生效。
图 3-5
在 WSL 中自动生成域名服务器
在做了修改之后,当 WSL 发行版重新启动时,您会发现/etc/resolv.conf
是用名称服务器自动生成的。让我们尝试向一个网站发送 ICMP 请求,只是为了检查名称解析是否有效;然后你会发现,在图 3-6 中,我们能够解析 google.com 并点击他们的目标服务器 IP 地址,开始接收 ping 响应。
图 3-6
名称解析在“resolv.conf”文件生成后生效
让我们来看看wsl.conf
文件的第三个也是最后一个子部分,称为[interop],它进一步定义了一个 Windows 进程是否可以从 WSL 启动,以及在两个操作系统之间共享 Windows 路径变量。
[互操作]部分
wsl.conf 文件的这一部分处理 Windows-Linux 互操作性的两个重要设置,下表 3-3 中提到了这两个设置。
本小节下的第一个属性是enabled
,如图 3-7 所示。如果enabled
属性被设置为false
,那么 WSL 将不支持从 Linux 运行任何 Windows 进程,比如 notepad.exe。图中的步骤 1 表明,当我们试图从 bash 运行 notepad.exe 时,它不能执行 Windows 格式的程序,并抛出一个错误。要解决这个问题,将属性enabled
的值更改为true
,并重启您的发行版以使 Windows 进程再次工作。
图 3-7
名称解析在生成resolv.conf
文件后生效
该子部分下的另一个属性是appendWindowsPath
,顾名思义,当该属性设置为“true”时,它会将 Windows PATH 变量中的文件夹追加到 Linux$PATH 环境变量中,如图 3-8 所示。同样,当通过将appendWindowsPath
设置为 false 来禁用它时,Windows PATH 变量的元素不会附加到 Linux $PATH 环境变量中。请确保终止并重新启动 Linux 发行版,以使这些更改生效。
图 3-9
使用 wslpath 实用工具翻译路径
图 3-8
将路径从 Windows PATH 变量追加到 Linux$PATH 环境变量
这就完成了一个/etc/wsl.conf
文件的三个子部分,这个文件的整个潜在目的是使超级用户能够调整[interop]、[automount]和[network]设置,这允许他们构建更好的混合体验。这有助于连接 Windows 和 Linux 两个世界,这样我们就可以轻松地转移东西,并使用最佳工具完成特定任务,而不考虑底层平台和许多其他功能,这些功能以前分别局限于 Windows 和 Linux 生态系统中。
现在,我们将学习通过共享环境变量和可配置值的能力,将 Windows 和 WSL 之间的这些混合体验带到另一个层次,这些环境变量和可配置值可以存在于两端的操作系统之间,并且可以将文件系统路径从 Linux 转换到 Windows,反之亦然。我们先从路径翻译开始。
Windows-Linux 路径转换–wsl Path
wslpath 是一个实用程序,执行从 WSL 路径到 Windows 路径的转换,反之亦然。下面是使用这个实用程序的语法,表 3-4 列出了所有可以与 wslpath 一起使用的输出参数。
语法:
wslpath [-m|-u|-w|-h] NAME[:line[:col]]
为了更好地理解这个工具,清单 3-1 和图 3-9 展示了一些执行路径转换的例子。
# by default translates Windows path to WSL path, equivalent to `-u`
wslpath 'C:\Users'
# you can also use '-a' to translate Windows path to Absolute WSL path format
wslpath -a 'temfile.txt'
# translates WSL path to Windows path using '-w'
wslpath -w '/mnt/c/Users'
# translates WSL path to Windows path using '-m'
# but with forward slash '/' instead of backward slash '\'
wslpath -m '/mnt/c/Users'
Listing 3-1Using wslpath utility to translate the paths
当我们想要从 WSL 运行 Windows 操作系统上的文件时,这个实用程序会非常方便,如图 3-10 中的以下示例,我正在运行放置在我的 Windows 文件系统上的 PowerShell 脚本,并且使用wslpath
,我能够将其转换到 Unix 路径,并通过 Linux 的 Windows 子系统内的pwsh
(这是在 Linux 上运行的 PowerShell 的开源版本)启动这个 PowerShell 脚本文件。如果我们仔细观察下面的例子,我们在一个(
图 3-10
使用 wslpath 实用工具启动 Windows PowerShell 脚本文件
现在我们已经了解了路径转换的工作原理,让我们看看 WSL 是如何让我们在 Windows 和 Linux 中共享环境变量的。
共享环境变量–WSLENV
从 Windows Insider build 17063 及更高版本开始,WSLENV 是一个特殊的环境变量,在 Windows 10 的早期版本中,当一个环境变量被另一个调用时,它允许在 Windows 和 Linux 发行版之间共享环境变量;WSL 中唯一可访问的 Windows 环境变量是 PATH。WSLENV 在 Windows 和 WSL 环境之间共享,包含一个共享环境变量列表。
一旦 WSL 会话关闭,将不会保存对 WSLENV 变量所做的任何更改。为了使更改持久化,您必须修改适当的配置文件,比如.profile
、.bash_rc
等等,这将在每次新的 WSL 会话启动时将 WSLENV 设置为所需的值。
WSL 和 Windows 之间的环境变量转换可以由表 3-5 中列出的下列 WSLENV 标志之一控制,并且这些标志可以根据需要组合在一起。
表 3-5
WSLENV 标志及其描述的列表
|旗
|
描述
|
| --- | --- |
| /p
| 指示将路径从 WSL 转换到 Windows,反之亦然 |
| /l
| 指示环境变量是路径列表 |
| /u
| 应该只为 Windows 中的 WSL 创建环境变量。 |
| /w
| 应该只从 WSL 为 Windows 创建环境变量。 |
Note
您可以将 WSLENV 的值设置为您喜欢的任何值。但是,如果您直接设置文件系统路径,而不是环境变量的名称,那么路径转换将不起作用。因此,建议将 WSLENV 设置为包含带有正确翻译标志的路径的环境变量。
例如,我们在 WSL 中创建一个变量,然后用/p 标志将其添加到 WSLENV 中,如图 3-11;现在,当我们试图从 cmd.exe 读取这个变量的值时,它将向您显示现在也可以在 Windows 上访问的转换后的路径。请注意,如果您没有 Windows 帐户的管理权限,您可能看不到 WSLENV 创建的环境变量:
图 3-11
从 WSL 在 Windows 中设置环境变量
$ export MYPATH=/mnt/c/Users
$ export WSLENV=MYPATH/p
$
$ cmd.exe
Microsoft Windows [Version 10.0.17763.348]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\admin> echo %MYPATH%
C:\Users
让我们再举一个例子,展示如何用标志/l
将冒号分隔(:)值的列表赋给 WSLENV,当从 Windows 访问环境变量时,该标志将这些路径转换为分号分隔的值,如图 3-12 所示:
图 3-12
设置具有多个值的环境变量
$ export MYPATHLIST=/mnt/c/Users:/mnt/c/temp
$ export WSLENV=MYPATHLIST/l
$
$ echo $MYPATHLIST
/mnt/c/Users:/mnt/c/temp
$
$ cmd.exe
Microsoft Windows [Version 10.0.17763.348]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\admin>echo %MYPATHLIST%
C:\Users;C:\Temp
WSLENV 标志/u
可用于指示环境变量仅在 Windows 的 WSL 上创建。这也可以与/p
标志结合使用(两者都可以组合成/up ),将路径转换成 Linux 特有的格式,如图 3-13 所示。另一方面,WSLENV 标志/w
以完全相反的方式工作,并在从 WSL 运行 Windows 时创建一个环境变量。
图 3-13
从 Windows 为 WSL 设置环境变量
WSLENV 变量还使我们能够使用各种可用的标志选项来定义多个共享环境变量。让我们看看它是如何工作的。
语法:
WSLENV=FORWSL/u:FORWIN/w:MYPATHLIST/l:TEMPDIR/p
这里,WSLENV 是用多个环境变量的列表定义的,后面跟有各自的 WSLENV 标志,用冒号分隔。这在我们希望以不同方式共享多个共享环境变量的场景中非常理想。例如,我们可以在 WSL 中运行以下命令,并在图 3-14 中看到输出:
图 3-14
一次设置多个环境变量
$ # creating environment variables and sharing with Windows using WSLENV
$ export FORWSL=/mnt/c
$ export FORWIN=/mnt/c/Data
$ export MYPATHLIST=/mnt/c/Users:/mnt/c/Data
$ export TEMPDIR=/mnt/c/temp
$ export WSLENV=FORWSL/u:FORWIN/w:MYPATHLIST/l:TEMPDIR/p
$ # checking the environment variables on Windows
$ cmd.exe # launch cmd prompt from WSL
C:\WINDOWS\system32> echo %FORWSL%
%FORWSL%
C:\WINDOWS\system32> echo %FORWIN%
/mnt/c/Data
C:\WINDOWS\system32> echo %MYPATHLIST%
C:\Users;C:\Data
C:\WINDOWS\system32> echo %TEMPDIR%
C:\Temp
摘要
在本章中,我们学习了使用wsl.conf
配置文件的各种 WSL 启动配置,以及该文件下允许的三个部分和可选设置:[automount]、[network]和[interop]。这些启动配置的组合可以挂载驱动器、设置名称解析、生成主机文件,并通过让您能够从 WSL 启动 Windows 应用来实现互操作性。在本章的后面,我们还介绍了 Windows-Linux 路径转换实用程序“wslpath”以及使用 WSLENV 在 Windows 和 Linux 操作系统之间共享环境变量。在下一章,我们将看看 Linux 发行版的 Windows 子系统的管理,比如安装、备份、恢复和发行版定制。
四、管理 WSL 发行版
在这一章中,我们将学习在 WSL 上管理我们的 Linux 发行版,这可以是从设置默认发行版,使用导出特性备份配置和设置,或者使用导入特性恢复发行版。除此之外,我们还将研究注销、卸载和重新安装 Linux 发行版的方法,并在本章末尾为 WSL 创建一个定制的 Linux 发行版。
让我们从获得您系统上的 Linux 发行版列表开始。
列表分布
首先,在我们能够管理我们的 WSL 发行版之前,我们必须确定安装在我们机器上的 Linux 发行版。为了在 Windows 10 版本 1903 或更高版本上实现这一点,我们可以将 wsl.exe 与“-l”或“- list”一起使用;这将列出所有可用的 Linux 发行版。请注意,在图 4-1 中,其中一个分布被突出显示为“默认”分布。这意味着这将在我们运行 wsl.exe 时启动,并且任何命令行参数都将传递给这个发行版:
图 4-1
已安装的 Linux 发行版列表
wsl -l
wsl --list
还有另一个参数--running
将只列出当前正在运行的 Linux 发行版,但是您只能将它与--list
参数开关一起使用:
wsl –list --running
正如您在图 4-2 中所看到的,一旦我们在步骤 2 中启动了一个 Linux 发行版,它就会出现在正在运行的发行版列表中。
图 4-2
列出所有正在运行的 Linux 发行版
现在我们知道了如何列出我们的 Linux 发行版,让我们弄清楚如何将这些 Linux 发行版中的一个设置为 WSL 的默认发行版。
设置默认发行版
为了设置默认分布,我们使用wsl.exe
的--setdefault
或-s
命令行参数,后面跟着目标分布名称作为参数,如图 4-3 所示。
图 4-4
在默认的 Linux 发行版中运行命令
图 4-3
在 WSL 中设置默认的 Linux 发行版
这也意味着你传递给wsl.exe
的任何命令将默认在你的默认 Linux 发行版中执行,如图 4-4 所示,简单地运行 wsl.exe 将启动一个默认 Linux 发行版的会话。
现在让我们来看看如何导出您的 Linux 发行包。备份的全部目的是将设置和配置保存在一个可分发的文件中,以便与任何人共享。
备份或导出 WSL 发行版
在 Linux 的 Windows 子系统上运行的分发包可以通过简单地将它导出为一个tar
文件来进行备份,这是“磁带归档”的缩写这些文件有”。tar”文件扩展名作为多个文件的集合,采用统一的 Unix 归档格式。这是存档和通过互联网发送多个文件的常用方法。
要导出您的 Linux 发行版,首先使用管理权限启动命令提示符。然后列出您使用“wsl.exe”安装的所有现有分发环境:
wsl --list –all
现在您已经知道了系统上 Linux 发行环境的名称,您可以再次使用wsl.exe
来定位并导出其中的一个,如图 4-5 所示,通过传递发行版名称和路径来导出这个文件:
图 4-5
导出 Linux 发行版
wsl --export Ubuntu-18.04 c:\temp\ubuntu1804.tar
wsl --export SLES-12 SLES.tar
这可能需要几分钟才能完成,这取决于您的 Linux 发行版的大小以及安装在其上的软件或软件包。一旦完成,你会发现你的发行版的根文件系统被备份为一个。tar”文件保存在导出时指定的位置。
恢复或导入 WSL 发行版
在前面的小节中,我们将我们的分发包导出到一个归档文件中。tar”文件。现在,可以在安装了 Linux 的 Windows 子系统的计算机上移动、共享和恢复这个归档文件。你所要做的就是用管理权限启动一个 Windows 命令提示符,并在wsl.exe
中使用--import
参数。将分发的名称作为参数传递,以便将根文件系统从。tar”文件指定:
wsl --import SLES-Imported c:\temp\ c:\temp\SLES.tar
在图 4-6 中,我们将“SUSE Linux Enterprise Server (SLES)”的备份副本导入到目录位置“c:\temp”中,自定义名称为“SLES 导入”。
图 4-6
导入 Linux 发行版
现在,您可以在列表中看到导入的 Linux 发行版,以及一个根文件系统的rootfs
文件夹,其中包含导入的发行版的所有文件、文件夹和包(图 4-7 )。这位于它被导入的目录中。
图 4-7
导入的 Linux 发行版的根文件系统
注销并卸载 WSL 发行版
取消发行版的注册意味着将发行版中的任何数据、设置和安装的软件与 Linux 的 Windows 子系统解除关联。一旦启动,它将永久销毁所有数据。但这也允许从 Microsoft Store 重新安装发行版的干净副本:
wsl --unregister kali-linux
正如你在图 4-8 中看到的,在取消注册“kali-linux”发行版后,它没有出现在我的 WSL 列表中。
图 4-8
注销 Linux 发行版
现在,如果你进入 Kali Linux 的微软商店页面并点击“Install ”,它将再次开始安装发行版。这意味着当你下次运行WSL 发行版时,将会安装一个新的发行版副本(图 4-9 ,允许你再次用新的 Unix 用户名和密码安装发行版。
图 4-9
注销 Linux 发行版后全新安装
另一种在 Windows 10 上卸载发行版的方法是点击开始菜单,搜索发行版的名称,然后点击卸载选项,如图 4-10 所示。
图 4-10
从开始菜单卸载 Linux 发行版
或者,如图 4-11 所示,你也可以进入开始菜单,运行设置,点击应用,搜索你的 Linux 发行版,然后点击卸载按钮。在“高级选项”部分有一个设置,比如“修复”你的 Linux 发行版,如果你的发行版出了问题并且你想修复它。
图 4-11
从“应用和功能”中卸载 Linux 发行版
创建自定义 WSL 发行版
最近,微软开源了工具和一个示例 Linux 发行版,目的是使开发人员和 Linux 发行版维护人员能够为 Linux 的 Windows 子系统创建定制的发行版包。这进一步增强了发行版维护者通过微软商店将 Linux 发行版发布给更多受众的能力,这些发行版可以在微软商店发布供下载。
这个项目名为 WSL-DistroLauncher,已经在 GitHub 上开源: https://github.com/Microsoft/WSL-DistroLauncher
。它是用于 Linux 的 Windows 子系统的 Linux 发行版 installer/launcher.exe 的 C++实现参考。这些发行包包括启动器应用,它负责在 WSL 中注册和安装发行版。在幕后,要为 Linux 发行版开发一个定制的 Windows 子系统,您需要一个头文件 wslapi.h,它提供了一组枚举和函数来配置、注册和启动定制发行版。
表 4-1 列出了前面提到的头文件提供的一些函数,你可以在这里了解更多的函数: https://docs.microsoft.com/en-us/windows/win32/api/wslapi/
。
表 4-1
WSL API(WSL API . h)头文件中的函数
|功能
|
描述
|
| --- | --- |
| WslConfigureDistribution() | 修改向 WSL 注册的分发的行为 |
| wslgettdetastributi oncconfiguration()的缩写 | 检索向 WSL 注册的分发的当前配置 |
| wslisdistributionn registered() | 已确定分发是否已注册到 wsl |
| WslLaunch () | 在特定分发的上下文中启动 WSL 进程 |
| wsllauncheck 我有() | 在特定分发的上下文中启动交互式 WSL 进程 |
| wslregistracrdistr 贡献() | 向 WSL 注册新的发行版 |
| WslUnregisterDis 依赖()) | 从 WSL 中注销分发 |
一旦发行版启动程序被构建并打包了所需的资产,比如图标文件、清单、证书等等,那么它就可以作为一个定制的 Linux 发行版加载到 Linux 的 Windows 子系统之上。构建的输出将把“launcher.exe”替换为一个定制的特定于发行版的名称,如 MyCustomDistro.exe,它将启动你的定制发行版,就像 Ubuntu1804.exe 或任何其他发行版启动器一样。使用这个项目,你还可以控制这个发行版启动器可以接受的命令行参数,甚至可以编写你自己的帮助文档,如图 4-12 所示。
图 4-12
发行版启动器命令行选项
摘要
在本章中,我们学习了如何管理 Linux 的 Windows 子系统的 Linux 发行版,我们首先列出了所有的 Linux 发行版,并根据它们的运行状态对它们进行了过滤,然后研究了如何为 WSL 设置默认发行版。后来,我们学习了如何备份 Linux 发行版,方法是将其导出为文件备份,然后导入到另一台计算机上,以在 WSL 中恢复 Linux 发行版。最后,我们介绍了一些在不需要的时候注销和卸载 Linux 发行版的方法,并以一个帮助为 WSL 创建定制 Linux 发行版的工具结束了本章。
在下一章中,我们将学习 Linux 版本 2 的 Windows 子系统(WSL2 ),并介绍两个版本之间的架构变化和功能差异。
五、探索 WSL2
在本章中,我们将了解 Linux 版本 2 的 Windows 子系统、它带来的新特性以及版本 1 和版本 2 之间的区别。我们还将学习如何在我们的机器上安装 WSL2,并使 Linux 发行版能够使用 WSL2。最后,我们将了解它的架构和功能。这一章背后的整个思想是向读者简要介绍 WSL2 中的架构变化,然后在此基础上构建剩余的章节,这将使读者更容易理解这个新版本的 WSL 背后的目的。我们开始吧。
WSL2 中的新特性
WSL2 是用于 Linux 的 Windows 子系统的最新和最好的版本。这个新版本是在牢记两个主要目标和最常见的社区请求的情况下构建的:
-
更好的文件 IO 性能–IO 性能的提高意味着更快的文件读写速度,而速度完全取决于文件访问操作的密集程度。诸如“git clone”、“npm install”、“apt update”或“apt upgrade”等任务的运行速度可能会快 2-3 倍,而在 WSL2 上解压缩压缩的 tarball 文件等任务的性能可能会比 WSL1 快 20 倍。
-
全面的系统调用支持–从运行在 Linux 版本 1 的 Windows 子系统上的 Linux 二进制文件生成的任何系统调用,用于执行诸如访问文件、请求内存、生成进程等功能,并被转换为底层操作系统的相应 Windows 系统调用。这是通过 WSL 团队开发的翻译层实现的,但是它有自己的挑战,并且不可能将每个 Linux 系统调用翻译成 Windows。不仅如此,微软的 WSL 团队还必须实现并调整这个翻译层,以适应 Linux 内核的任何变化。
因此,微软决定 WSL2 将包含自己的 Linux 内核,以完全支持系统调用兼容性,并使其易于提供内核更新。这为 Docker 和其他系统等更多应用在 WSL2 中无缝运行打开了窗口。另外,微软维护着 Linux 内核的一个分支;这意味着对 Linux 内核的任何更新都不必等待更长时间才能到达 Windows,并且可以更快地快速更新、发布和分发给最终用户。所有内核改进和安全修复都可以通过 Windows updates 获得。
在牢记这些目标的同时,保持相同的用户体验而不改变 WSL1 用户已经习惯的许多东西也很重要。
WSL1 使用户能够在 Windows 子系统上运行 ELF64 Linux 二进制文件,但在版本 2 中,在 Linux 二进制文件如何与 Windows 操作系统和系统硬件交互方面有所变化,这主要是因为现在微软通过 WSL2 向 Windows 提供了一个具有更高级虚拟化技术的 Linux 内核。由于现在有了完整的内核,WSL2 还添加了 ELF32 二进制支持或 Linux 内核支持的任何其他特性。
在开始使用 WSL2 之前,有两个主要的先决条件需要满足;首先,WSL2 仅在 Windows 10 build 18917 或更高版本中可用。其次,请加入如图 5-1 所示的“Windows Insider Program”,选择快环或慢环(提供更稳定的更新)以获得 WSL2 附带的 Windows build 的预览版。如果您已经在运行 Windows 10 version 2004,请忽略第二个设置。
图 5-1
选择 Windows Insider 计划
一旦全面上市,WSL2 将很快(或者当你阅读本文时已经)成为 Windows 10 version 2004 的一部分。这是微软通过 Windows Update 简化安装体验,而不是将其与操作系统映像一起发布,从而改进 Linux 内核服务模型的一步。这意味着您的所有 Linux 内核更新将通过 Windows Update 无缝地传递到您的系统,就像任何软件、补丁和驱动程序一样。你所要做的就是点击 Windows updates 设置中的“检查更新”按钮,然后安装这个更新,如图 5-2 所示。
图 5-2
更新到 Windows 10 版
在本章的这一点上,你一定在想:WSL1 和我在其上配置的 Linux 发行版会发生什么?微软会停止或弃用 WSL1 吗?要回答这个问题,没有什么可担心的,因为微软既没有任何意图也没有计划弃用 WSL1,而且这两个版本是并行运行的。这意味着 WSL1 和 WSL2 Linux 环境可以并行运行,并且您可以在任何需要的时候升级和降级任何发行版。在本章的后面,我们将研究这是如何做到的。
WSL2 架构
Windows Subsystem for Linux 2 附带的 Linux 内核运行在一个轻量级实用虚拟机上,该虚拟机最初是为服务器场景开发的,用于在一台主机上运行大量基于 Hyper-V 的隔离容器,并支持更快的引导时间。
这不是传统的虚拟机体验,而是最新、最棒的虚拟化(基于 Hyper-V)技术,旨在减少资源占用、启动时间以及创建、配置和管理传统虚拟机所花费的时间。表 5-1 提供了一些差异,以进一步明确这种区别。
表 5-1
WSL 使用的传统虚拟机和轻量级实用虚拟机的比较
|传统虚拟机
|
WSL2 轻量级实用程序虚拟机
|
| --- | --- |
| 客户操作系统与主机操作系统相隔离。 | 客户操作系统与主机操作系统紧密集成。 |
| 较慢的启动时间 | 更快的启动时间,即不到 1 秒 |
| 更大的内存消耗 | 更低的内存消耗 |
| 创建和管理这些虚拟机。 | 自动设置,仅在需要时运行 |
让我们更深入地挖掘一下,理解当一个 WSL2 Linux 发行版发布时,在幕后发生了什么。首先,确保所有 WSL 实例都已终止:
wsl --shutdown
然后,我们尝试在默认的 WSL2 发行版上执行一个命令,一旦命令执行,它将变为“Running”状态。现在,要验证这一点,请使用管理权限启动 PowerShell 控制台,并使用hcsdiag.exe list
命令列出所有正在运行的 Hyper-V 容器,这是一个诊断工具,用于检查由主机计算服务管理的 Windows 容器,然后这将演示在不到一秒钟的时间内即时创建的轻量级 VM 容器,如图 5-3 所示。
图 5-3
主机计算服务创建一个轻量级虚拟机
另外两个容器只是已经在我的主机上创建的 Hyper-V 虚拟机,并且处于运行状态。如图 5-4 所示,您可以观察到来自hcsdag.exe list
的 GUID 和来自Get-VM
cmdlet 的结果相匹配。
图 5-4
其他 Hyper-V 虚拟机
但是,如果我们再次关闭所有的 WSL2 实例,并在我的 WSL2 Linux 发行版上重新运行一个命令,那么它将在一个新的容器中为轻量级实用 VM 启动,并带有一个新的 GUID,如图 5-5 所示。
图 5-5
每次运行命令时,都会启动一个新的轻量级虚拟机
现在我们已经了解了 Linux 内核在这个轻量级虚拟机中运行,让我们进一步了解图 5-6 所示的 WSL2 的实际架构,以及从 Windows 操作系统启动 Linux 应用时所涉及的步骤,以及它如何与 Linux 虚拟机集成,从而为我们提供无缝的、两全其美的体验。
图 5-6
WSL2 架构图和工作流
以下是演示此工作流的组件,您可以跟随前面的图像进行操作:
-
“wsl.exe”用于列出发行版,启动并与通过
LxssManager
服务启用的子系统交互。 -
保存已安装和正在运行的发行版列表,然后调用主机计算服务。
-
主机计算服务是使 WSL2 成为可能的 Hyper-V 虚拟化技术的一部分;这将启动一个使用 Linux 内核的轻量级实用 VM。
-
然后,VM 被映射到您的 Linux 发行版的文件系统,并调用一个
init
进程来初始化和运行您的应用。 -
在这之后,从 Windows 端到您的应用的标准输入建立了一个中继,在我们的例子中是
bash
,这样就在 Linux 和 Windows 端之间建立了通信,这样当一个命令从 Windows 端运行时,我们就可以看到我们的 Linux 应用内部发生了什么。基本上,Windows 标准输入向套接字发送命令,然后在轻量级客户操作系统中从套接字读取这些命令,最后这个套接字是 Linux 应用(如“bash”)的标准输入。
这个虚拟机只在您运行您的 Linux 应用时运行,如果您终止您的 Linux 应用或终止wsl.exe
,
,这个轻量级虚拟机就会消失。如果您重新启动一个 Linux 应用,这个虚拟机将会重新启动并再次启动。
请注意,无论您的机器上运行多少个 WSL2 Linux 发行版,它们都将在一个轻量级的实用 VM 中启动。这意味着每个用户只创建一个 Linux utility VM,以便于使用 WSL2 运行多个发行版。每个发行版都在一个独立的容器中运行,所以这应该不成问题。这是通过使用 Linux 名称空间 API http://man7.org/linux/man-pages/man7/namespaces.7.html
来实现的,目的是通过让所有发行版都运行在单个虚拟机上来减少内存和资源占用。
另一方面,为了访问 WSL2 中的文件,像/mnt/c
这样的挂载点使用 9P 协议文件服务器来处理这样的请求。Linux 内核充当运行在轻量级虚拟机上的 9P 协议客户端,即运行在客户操作系统上,然后客户操作系统向运行在主机操作系统(Windows 10)上的 9P 服务器发出请求,以从 Windows 访问 Linux 文件。
安装和设置
Linux 的 Windows 子系统是 Windows 10 中的一个特性,但是要为 WSL1 启用这个特性还需要一些步骤,我们在前面的章节中已经讨论过了;除此之外,还讨论了启用“虚拟机平台”功能的要求。一旦满足了这两个先决条件,我们就可以继续将我们的 WSL1 Linux 发行版转换成 WSL2,或者选择 WSL2 作为所有未来安装的 Linux 发行版的默认版本。
让我们一步一步来。
为 Linux 1 启用 Windows 子系统
如果你还没有在 Windows 10 上使用 Linux,现在正是时候。您可以首先从 Windows 特性中启用 Linux 的 Windows 子系统,如以下步骤所述:
图 5-7
搜索“Windows 功能”
-
在 Windows 任务栏上,在屏幕的左下角,单击“开始”按钮。
-
现在在搜索框中搜索“打开 Windows 功能”,然后点击顶部的结果,如图 5-7 所示。
-
这将打开一个“Windows 功能”对话框。滚动到底部,确保选中“Windows Subsystem for Linux”功能框。单击确定并退出此对话框。
-
保存所有打开的工作,因为系统可能会提示您重新启动系统。按照任何必要的提示关闭正在运行的应用。
一旦启用了 WSL1 并且您的系统已经重启,我们现在需要启用“虚拟机平台”为此,请执行以下步骤。请注意,只有当您的计算机支持硬件虚拟化并且在 BIOS 或 UEFI 中启用了该功能时,才能执行这些步骤。
启用“虚拟机平台”
图 5-9
将 WSL2 设置为新 Linux 发行版的默认架构
图 5-8
启用虚拟机平台
-
使用管理权限启动 PowerShell 会话。
-
在 PowerShell 中运行以下命令,如果您看到如图 5-8 所示的结果,那么该特性已经成功启用。
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
-
如果出现提示,请重新启动系统。
完成这些步骤后,我们现在可以将我们的 Linux 发行版转换为 Linux 2 的 Windows 子系统,或者选择 WSL2 作为运行这些发行版的默认架构。
为 Linux 2 启用 Windows 子系统
在启用 WSL2 之前,我们需要遵循一些临时步骤,其中我们需要手动安装一个 Linux 内核更新。在不久的将来,当 WSL 更新开始通过 Windows Update 交付时,将不再需要这些手动步骤:
-
从以下网址下载 WSL2 Linux 内核更新:
https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
-
下载完成后,双击下载位置的“wsl_update_x64.msi”文件运行并应用此更新。
-
一旦应用了更新,转到开始菜单,用管理权限启动 PowerShell.exe。
-
现在运行下面的命令,如图 5-9 所示,让 WSL2 成为以后您将在系统上安装的所有新 Linux 发行版的默认架构。这不会改变任何运行在 WSL1 上的现有 Linux 发行版,两者可以共存。
wsl --set-default-version 2
- 要配置任何现有的 Linux 发行版来使用 WSL2 架构,您可以通过运行
wsl --set-version
和 Linux 发行版名称,后跟“2”来实现,如图 5-10 所示:
wsl --set-version kali-linux 2
验证 Linux 分发子系统平台并回滚到 WSL1
使用以下命令可以很容易地验证您的 Linux 发行版所使用的架构:
wsl --list --verbose
这将列出所有的 Linux 发行版及其版本信息,正如我们在图 5-11 中看到的,我们从上一步对kali-linux
发行版的转换在这里得到了反映。
图 5-10
将 WSL1 Linux 发行版转换为 WSL2
如果我们想使用旧的 WSL1 架构,我们可以很容易地将我们的发行版转换成使用 WSL1,如图 5-12 和下面的例子所示:
wsl --set-version kali-linux 1
如果您觉得 WSL2 仍然是实验性的软件,您可能不想在您的主要计算机系统上运行它,而是在一个虚拟机上评估这个软件。但是在您可以在虚拟机上使用 WSL 之前,您可能需要了解一些事情和一些必需的配置。
在虚拟机中运行 WSL2
您也可以在基于 Hyper-V 的虚拟机上运行 Windows 子系统 for Linux。您所要做的就是确保虚拟机上启用了嵌套虚拟化,如图 5-13 所示。
我们可以使用 PowerShell 来启用该设置。为此,请使用管理权限从 PowerShell 控制台运行以下命令。只需确保提供目标虚拟机的名称。只有当机器处于停止状态时,才能应用此设置,因为在机器运行时,您不能更改处理器配置。
Get-VM 'Name' | Set-VMProcessor -ExposeVirtualizationExtensions $true
当 Hyper-V 在您的系统上使用时,一些主要的第三方虚拟化应用无法工作。这意味着您可能无法同时运行 WSL 和 VMware 和 VirtualBox。但是,这些主要的虚拟化技术提供商最近发布了支持 WSL2 和 Hyper-V 的软件版本。以下是其发布页面的链接,供您参考:
从 WSL1 到 WSL2 改变了什么用户体验?
微软已经尽最大努力保持两种架构的用户体验一致,但尽管如此,当从 WSL1 切换到 WSL2 时,WSL2 用户将观察到整体用户体验的三大变化。
更快的文件性能
体验更快的文件性能,但为了实现这一点,建议将您的所有文件保留在 Linux 发行版的根文件系统下,因为现在我们在 Linux 2 的 Windows 子系统上有一个完整的 Linux 内核,可以轻松处理这些文件密集型操作,与 WSL1 相比,它的速度快了几倍。
为了测试性能,我们将使用包管理器测试软件安装,并在 WSL1 和 WSL2 上使用 curl 请求测试 web 套接字:
time sudo apt install ruby –y
time curl google.com
图 5-14 演示了在 WSL1 上安装“ruby”大约需要 30 秒,而对 google.com 的 web 请求在 5 秒内返回结果。现在让我们在 WSL2 上尝试相同的测试,但是请确保您在相同的 Linux 发行版上运行这个测试。这个测试是在 Ubuntu 18.04 LTS Linux 发行版上进行的,所以我必须将 WSL 架构版本从 WSL1 更改为 WSL2,并从发行版中删除已安装的“ruby”软件来执行一个新的测试。
图 5-11
验证 Linux 发行版 WSL 版本
我们在 WSL2 上的测试表明,安装在不到 5 秒的时间内完成(比 WSL1 快 6 倍),web 请求用了 1/10 秒(比 WSL2 快 50 倍)来完成请求并获得结果,如图 5-15 中突出显示的。与 Windows Subsystem for Linux 版本 1 架构相比,这是一个显著的性能提升。
WSL2 现在使用虚拟硬件磁盘(VHD)
因为 WSL2 运行在一个轻量级的实用虚拟机上,就像任何其他虚拟机一样,它将所有的 Linux 文件存储在一个使用 ext4 文件系统的虚拟硬件磁盘(VHD)中。VHD 的最大大小最初设置为 256GB,根据您的使用情况,此 VHD 会自动增长和收缩以满足您的存储需求,直到达到此最大限制。一旦达到限制,您开始得到“磁盘空间不足”的错误。为了修复这些错误,您必须通过执行以下步骤来扩展 VHD 大小:
- 使用以下命令终止所有正在运行的 WSL 实例:
图 5-12
将 Linux 分发平台回滚到 WSL1
-
Use PowerShell to find your Linux distribution’s installation package name
PackageFamilyName
and the full path to its ext4.vhdx file:$pkgFamilyName = (Get-AppxPackage -Name "*ubuntu*").PackageFamilyName $Path = "$env:LOCALAPPDATA\Packages\$pkgFamilyName\LocalState\*.vhdx" $vhd = Get-ChildItem $Path
最后,我们使用 Hyper-V 模块中的
Resize-VHD
cmdlet 将这个虚拟硬件磁盘扩展到我们想要的大小,如图 5-16 所示:
wsl --shutdown
Resize-VHD -Path $VHD.FullName -SizeBytes <size>
-
一旦调整完成并且没有出现任何错误,就像前面的图片一样,然后重新启动您的 WSL2 Linux 发行版。
-
现在,我们必须从 WSL 内部扩展文件系统的大小,并让它知道我们在上一步中执行的更改。为此,我们必须在您的 WSL 发行版中运行以下命令,以确保文件系统已挂载:
sudo mount -t devtmpfs none /dev
完成后,我们必须通过使用以下命令过滤掉类型为ext4
的文件系统来找到正在使用的根文件系统,这将突出显示我们想要作为目标的挂载点,如图 5-17 所示:
图 5-20
从 Windows 访问 WSL2 上的 Node.js 服务器
图 5-19
从 WSL2 访问 Windows 上的 Node.js 服务器
图 5-18
WSL2 有专用的虚拟以太网适配器
图 5-17
在 WSL2 中扩展 VHD
图 5-16
调整 WSL2 虚拟硬件磁盘的大小
图 5-15
WSL2 上的文件和 web 套接字性能
图 5-14
WSL1 上的文件和 web 套接字性能
图 5-13
在 Hyper-V 虚拟机上启用 WSL
- 请从以下示例中复制此项的名称,如/dev/sdb,并运行以下命令:
mount | grep ext4
sudo resize2fs /dev/sd**
确保将前面命令中的星号(*)替换为命令中的正确字符,如果运行成功且没有错误,则 VHD 扩展完成。如果 Linux 发行版上没有安装resize2fs
,可能需要安装它。
网络变化和注意事项
当使用 WSL1 Linux 发行版时,所有的 Linux 调用都被转换成 Windows 系统调用,如果您的系统使用局域网,那么任何运行在 WSL 上的应用也将直接使用局域网。但是这种行为在 WSL2 中发生了变化,因为 WSL2 运行在一个轻量级的实用虚拟机上,并且有一个虚拟化的以太网适配器,该适配器分配有自己的 IP 地址,如图 5-18 所示。
除此之外,由于 WSL2 仍然是一个新产品,还在开发中,您会发现在 WSL2 的早期版本中,您必须使用您的主机的 IP 地址从 Linux 访问 Windows 操作系统,但是在以后的版本中,这种体验会更加顺畅。
从 Linux 访问 Windows 应用
例如,我的计算机运行的是 Windows 10 version 2004(OS build 19041.172),我有一个简单的 Node.js 服务器运行在 Windows 10 端,我可以通过一个简单的“curl”命令从 WSL2 内部使用环回地址轻松访问服务器,如图 5-19 所示。
从 Windows 访问 Linux 应用
就像我们在前面的例子中从 Linux 访问一个 Windows 应用一样,我们也可以从 Windows 10 端的http://localhost
访问一个 Linux 应用,一个运行在 WSL Linux 发行版中的 Node.js 服务器。图 5-20 演示了一个 PowerShell Invoke-WebRequest
命令来访问运行在 WSL 上的端点。
摘要
在这一章中,我们学习了 WSL2 中的新特性和改进,以及将完整的 Linux 内核移植到 Windows 10 以支持新版本的 Windows Linux 子系统的目的。我们启用并执行了 WSL2 的安装,并学会了并行运行 WSL1 和 WSL2 子系统平台。后来,我们还研究了将 WSL1 Linux 发行版转换为 WSL2 兼容发行版,然后对 WSL2 中的文件系统和网络性能改进进行了基准测试。在本章快结束时,我们在 WSL2 虚拟硬盘上执行了 resize 操作,并以 WSL2 中的网络变化结束了本章。在下一章中,我们将学习 Linux 文件系统的 Windows 子系统,它的架构,以及 WSL 文件系统如何实现 Linux 和 Windows 之间的互操作性。
六、文件系统
在本章中,我们将了解文件系统如何无缝地工作,就像您在 Linux 操作系统中处理 Linux 文件一样,此外,它还使开发人员和高级用户能够使用完整的 Windows 和 Linux 互操作性来提高他们的工作效率。从一开始,Windows 子系统 for Linux 的目的之一就是将两个世界的优点结合在一起,而不是像传统虚拟机那样将 Windows 和 Linux 操作系统相互隔离,在传统虚拟机中,您只能使用网络共享和其他一些解决方案来访问主机和客户机操作系统之间的文件。相反,我们的目标是以这样一种方式集成它们,即 WSL 可以直接访问 Windows 文件,而 Windows 可以访问运行在 WSL 上的 Linux 发行版中的文件。
在我们深入研究文件系统之前,让我们先了解一些使 Linux 文件系统的 Windows 子系统工作的基本组件。
文件系统组件
为了支持在 Windows 上运行的 Linux 文件系统,Linux 的 Windows 子系统必须将在 Linux 文件系统上执行的所有用户操作转换为 NT 内核操作。此外,用户应该能够从运行在 WSL 之上的 Linux 发行版中访问 Windows 文件。
虚拟文件系统
为了实现这一点,WSL 在 lxcore.sys 中内置了一个 VFS 组件,该组件模拟 Linux 操作系统的虚拟文件系统(VFS)。VFS 在 Linux 操作系统中的作用是提供一个抽象层来管理 Linux 上任何时候挂载的所有文件系统。这种抽象简化了常见的操作(如 open、read、chmod、stat)和实现,而不考虑可以共存的底层文件系统。其中一些文件系统如下:
-
狼
-
drvfs
-
文件系统
-
普罗普斯
-
sysfs
让我们分别研究一下这些问题。
狼
这是 WSL 上的主要文件系统,用于存储所有 Linux 系统文件和您的主目录,其功能几乎与 Linux 虚拟文件系统(VFS)相同。从技术上讲,所有文件都在 Windows 上,WSL 通过模拟内部 Linux 文件系统的 Linux 行为来提供对这些文件的完全访问,例如添加到每个 Linux 发行版中的以下目录:
-
/
-
/root
-
/home
但是这个文件系统的目的不是互操作性,而是为用户提供他们熟悉的 Linux 体验,比如/home 或/root 目录。也就是说,如果从 Windows 端添加一个新文件,它不具有 volfs 理解的正确的扩展属性,它们会被简单地忽略,并且这样的文件对于 Linux 的 Windows 子系统中的 Linux 发行版变得不可用。
让我们举一个从 Windows 到这个文件系统的文件创建的例子来更好地理解它。在第一种方法中,我们尝试在我的 Windows 10 机器上的%LocalAppData%\文件夹中的/home/prateek 目录下创建一个文件,我的 Ubuntu 18.04 Linux 发行版的所有包文件都放在这个文件夹中。
请注意,第一种方法并不是向 WSL 上的 Linux 发行版添加文件的推荐方法,它可能会导致文件损坏和差异。建议不要从 Windows 端接触该文件夹:
$rootFS = "Packages\<package name>\LocalState\rootfs\home\<username>"
$param1 = @{
ItemType = 'File'
Path = "$env:LOCALAPPDATA\$rootFS\file1.txt"
}
New-Item @param1 -Verbose
当我们从 Windows 端的 PowerShell 控制台运行上述命令时,我们看到已经从 PowerShell 控制台创建了 file1.txt 文件。可以从%LocalAppData%文件夹中验证这一点。但是如果你仔细观察图 6-1 ,在 WSL 上运行的 Ubuntu 发行版中缺少 file1.txt。
图 6-1
不建议从%LocalAppData%文件夹访问 Linux 文件
另一方面,当我们使用第二种方法创建名为“file2.txt”的文件时,这是通过 UNC 路径\wsl$\进行的,如图 6-2 所示,使用下面的代码示例,这不仅创建了该文件,而且该文件现在也可以在 Linux 的 Windows 子系统中使用,这与第一种方法不同。再次强调,第二种方法是从 Windows 创建 WSL 文件的推荐方法,从位于%LocalAppData%文件夹中的 Linux 包创建或编辑文件不是最佳做法:
图 6-2
使用\wsl$\访问 Linux 文件,推荐的方法
$param2 = @{
ItemType = 'File'
Path = \\wsl$\Ubuntu-18.04\home\prateek\file2.txt
}
New-Item @param2 -Verbose
使用 UNC 路径\WSL$\
图 6-3
添加到 NTFS 文件中的扩展属性出现在 WSL
drvfs
该文件系统自动安装在 Linux 发行版上,以提供与 Windows 的互操作性,因此可以从 Linux 的 Windows 子系统访问安装在 NT 文件系统上的驱动器,如图 6-4 所示。drvfs 目前只支持新技术文件系统(NTFS)和微软最新的文件系统,弹性文件系统(ReFS)。Linux 的 Windows 子系统会自动将固定驱动器挂载到/mnt 文件夹下
图 6-4
Windows NTFS 驱动器作为 drvfs 文件系统安装在 WSL 上
-
/分钟/c
-
/mnt/d
当我们在 drvfs 窗口中打开文件时,文件权限通过访问控制列表(ACL)适用,这意味着即使您在 WSL 环境中使用sudo
作为 root 权限,也不意味着您可以访问通过 drvfs 映射的每个 NTFS 文件夹下的文件。例如,如果您尝试访问/mnt/c/Windows,仅有 sudo 权限是不够的,您可能必须使用提升的权限启动 WSL 实例。
文件系统
tmpfs 中的所有内容都是临时的,因为不会在您的永久存储(如硬盘)上创建任何文件。相反,所有文件都保存在易失性存储器中,如虚拟内存。这意味着如果您卸载一个 tmpfs,那么其中存储的所有内容都将丢失。
tmpfs 使用内存(RAM)和基于磁盘的交换空间的组合来创建文件系统,由于它使用 RAM,因此与写入磁盘相比,读取和写入数据非常快。如图 6-5 所示,/dev
和/run
等文件系统挂载了多个目录。
图 6-5
tmpfs 是一个临时文件系统
procfs,sysfs
procfs 和 sysfs 是特殊的文件系统,它们表示系统信息,如 CPU、进程、驱动程序、设备和配置,这些信息大多是在读取时动态生成的。在后台,WSL 从 Windows NT 内核查询这些信息,而不与 NTFS 进行任何交互。
procfs 是较早的实现,其中大多数与系统相关的信息可以在目录/proc
中找到,如图 6-6 和下面的例子所示,我们可以使用
图 6-6
通过/proc 文件系统访问系统信息
cat /proc/uptime
and verify the Linux kernel version:
cat /proc/version
从 Linux 内核版本 2.6 开始,实现了一个名为 sysfs 的新文件系统,它以一种更加结构化和易于搜索的方式来表示/sys
处的信息。/sys
可用于获取电源设置或以太网端口的物理地址等信息,如图 6-7 所示。
图 6-7
通过/sys 文件系统访问系统信息
多个 UNC 提供程序(MUP)
多 UNC 提供程序(MUP)是 mup.sys 二进制文件的内核模式组件部分,负责将任何基于 UNC 的远程文件系统访问重定向到可以满足此类文件系统请求的网络重定向程序(UNC 提供程序)。
基本上,MUP 确定哪个提供程序可以在基于名称的操作中处理 UNC 路径,这也称为“前缀解析”如图 6-8 所示,向这些网络提供商查询前缀解析的顺序基于以下注册表条目的逗号分隔值:
图 6-8
UNC 路径前缀解析的网络提供商列表
$path = 'HKLM:\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order\'
(Get-ItemProperty $path).ProviderOrder -split ','
当 WSL 实例启动时,会启动一个 init 进程,该进程在 WSL 上设置一个 9P 服务器和一个用于通信的 Unix 套接字,然后使用 LXSS 管理器服务注册 WSL 包名,并将一个指向 9P 文件服务器的 Unix 套接字注册到 MUP 使用的 9P 重定向器。
因此,当来自 Windows 的用户试图访问 wsl 文件系统的\wsl$\
9P(九号计划协议)
9P(或 Plan 9 文件系统协议)是一种网络协议,用于建立一个 9 文件服务器(在 WSL 上)和一个客户机(在 Windows 上),以桥接 Windows 和 Linux 文件系统,并提供无缝的互操作性。使用此协议而不使用 SMB 协议有多种原因,SMB 协议在 Windows 操作系统上已经非常流行。一些原因如下:
-
默认情况下,SMB 可能没有安装在您的系统上。
-
它可能已经过配置,运行多个 SMB 实例并覆盖配置并不明智。
-
如果一个 Linux 发行版没有 Samba,微软就不能发货,因为它是 GNU GPL 许可的,不能和 Windows 10 操作系统一起发货。
-
与更简单和直接的 9P 相比,SMB 在 Linux 的 Windows 子系统下实现起来很复杂和困难。
WSL 文件系统架构
在我们了解 WSL 的文件系统架构以及如何从 Windows 访问文件到 Linux 以及从 Linux 访问文件之前,让我们首先了解设置工作流,这是通过以下步骤实现文件系统之间的互操作性的要求,这些步骤在图 6-9 中用浅蓝色编号的标签突出显示:
图 6-9
WSL1 文件系统架构
-
启动 WSL.exe 实例时,它会与 LXSS 管理器服务进行交互。
-
LXSS.sys
然后与 Linux 的 Windows 子系统通信,以运行init
进程。 -
这个
init
进程还负责初始化子系统,并在 WSL 中建立一个 Plan 9 协议文件服务器。 -
然后,该服务器将与 LXSS 管理器服务协作,为文件系统通信建立一个 Unix 套接字。
-
一旦完成,Linux 发行版的名称和 Unix 套接字就被注册到 9P 重定向器,以使它知道任何解析到 UNC 路径\wsl$\
的请求应该连接到哪里。
一旦初始设置完成,就需要执行以下步骤,以便从 Windows 到运行在 WSL 上的 Linux 操作系统访问文件:
-
像 CMD.exe 或 PowerShell.exe 这样的 Windows 进程试图使用 UNC 路径\wsl$\
访问 WSL 上的 Linux 文件。 -
此请求被传输到 MUP(多 UNC 提供程序),它尝试解析此路径并连接到适当的远程文件系统。
-
MUP 通过查找已经为此类请求注册的网络提供商或重定向器来实现这一点。
-
因为在前面的小节中,已经为 WSL 在 9P 重定向器上注册了一个 Unix 套接字来处理这样的请求,所以这个套接字将被 MUP 用来创建一个到 WSL 上的 Linux 文件系统的 9P 文件服务器连接。
-
现在,这个 9P 服务器可以与 lxcore.sys 进行通信,以便于使用虚拟文件系统(VFS)从 Windows 进行任何文件系统访问或操作,并模拟 Windows 系统调用到 Linux 系统调用。
Note
WSL1 和 WSL2 的文件系统架构有一个主要区别,即在 WSL1 上,所有文件都使用 NTFS 存储在 Windows 驱动器上,而在 WSL2 上,Linux 文件使用 ext4 文件系统存储在虚拟硬件磁盘(VHD)上。
Windows-Linux 区分大小写
使用CreateFile
API 创建文件时,Windows 应用能够传递一个标志 FILE_FLAG_POSIX_SEMANTICS,该标志表示文件路径已启用区分大小写。你可以在这里阅读更多关于这个 API 和标志: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
。自 Windows XP 以来,Windows 操作系统就具有这种功能,但默认情况下,它会被全局注册表覆盖。
为了支持在 WSL 上运行的 Linux 应用所使用的区分大小写的文件,Linux 的 Windows 子系统具有其他机制来绕过全局注册表设置,以设置 FILE_FLAG_POSIX_SEMANTICS 标志,从而像 Linux 一样为用户提供区分大小写的体验,而且还使 Windows 应用可以访问这些文件。
Linux 的 Windows 子系统使用另一种机制,它本身绕过那个注册表项,允许我们执行区分大小写的文件系统操作。这就是为什么在 WSL 中运行的 Linux 应用可以使用仅大小写不同的文件名,就像它们在真正的 Linux 上一样,即使使用了全局注册表项集。总是有改变注册表设置的选项,但我们不要忘记这是一个全局设置,改变它将改变所有驱动器的大小写敏感性,这可能不是我们想要的,并可能导致跨应用的意外行为,甚至破坏其他一些应用。
为了克服这一缺点,实现了一个新的区分大小写标志,以在目录级别而不是全局设置上启用或禁用区分大小写,并且不考虑该目录中文件的 FILE_FLAG_POSIX_SEMANTICS 标志。这个新标志允许一个目录中存在两个同名但大小写不同的文件,并且 Windows 应用可以访问这两个文件。
由于 Windows 10 内部版本为 17107,我们可以使用 fsutil.exe 通过以下命令语法查看或修改此标志:
fsutil.exe file queryCaseSensitiveInfo <directory path>
fsutil.exe file setCaseSensitiveInfo <directory path> <enable\disable>
按照下列步骤使用 fsutil.exe 启用区分大小写的文件:
-
首先,使用管理权限启动 PowerShell 控制台并创建一个新目录,因为此标志只能应用于目录级别:
-
让我们测试在上一步中刚刚创建的目录上的标志。默认情况下,区分大小写是“禁用的”:
mkdir testdir | Out-Null
图 6-10
查询和修改 NTFS 上区分大小写属性
-
现在,如果我们试图创建两个名称相同但大小写不同的文件,那么第二个命令会覆盖第一个文件,并且不会创建第二个文件,因为仍然不支持区分大小写:
'test1' | Out-File D:\testdir\foo.txt 'test2' | Out-File D:\testdir\FOO.txt ls D:\testdir\
-
现在,让我们使用 fsutil.exe 设置标志,并重新尝试创建一个同名但大小写不同的文件:
fsutil.exe file setCaseSensitiveInfo D:\testdir\ enable 'test2' | Out-File D:\testdir\FOO.txt
-
这次将创建一个新文件,如图 6-10 所示,无论大小写,您都可以在目录中看到“foo.txt”和“FOO.txt”文件:
fsutil.exe file QueryCaseSensitiveInfo D:\testdir\
ls D:\testdir\
在 Windows 10 build 17692 中,通过基于每个目录的扩展属性system.wsl_case_sensitive
,可以在 Linux 的 Windows 子系统中方便地调整区分大小写。要查看或修改这个扩展属性,我们可以使用 Ubuntu 上的getfattr
和setfattr
命令,您可能需要使用
sudo apt install attr
要启用该属性,请将其设置为“1”,而“0”则禁用该属性。
Linux 的 Windows 子系统允许我们使用/etc/wsl.conf
文件的[automount]部分来控制 drvfs 挂载选项的大小写敏感性,默认情况下,WSL 上挂载的这些 Windows 驱动器是不区分大小写的。这意味着当 case=off 被设置时,在“drvfs”挂载上创建的任何新目录将是不区分大小写的。
让我们试试这个:当我检查我安装的驱动器时,我看到默认情况下drvfs
被设置为 case=off:
mount | grep case
如图 6-11 所示,当我们创建一个新目录并使用getdattr
检查system.wsl_case_sensitive
扩展属性时,我们观察到它被设置为“0 ”,这意味着该目录不区分大小写:
图 6-11
使用“getfattr”在 WSL 中查询区分大小写
mkdir /mnt/d/newdir
cd /mnt/d/
getfattr -n system.wsl_case_sensitive newdir
因此,如果我们试图创建两个具有相同名称和不同大小写的文件,那么第一个文件将被第二个命令覆盖,并且只存在一个文件:
touch newdir/file.txt
touch newdir/FILE.txt
ls newdir/
为了从 WSL 内部启用区分大小写,我们在目录上启用了扩展属性,如下例所示:
setfattr --name system.wsl_case_sensitive --value 1 newdir
getfattr -n system.wsl_case_sensitive newdir
现在,如果我们创建一个大小写不同的文件,那么这两个文件将以相同的名称和不同的大小写“file.txt”和“FILE.txt”创建,如图 6-12 所示:
图 6-12
使用“setfattr”修改 WSL 中每个目录的区分大小写
touch newdir/FILE.txt
ls newdir/
Linux 的 Windows 子系统还允许将/etc/wsl.conf
文件中的挂载选项设置为case=dir
,这意味着所有创建的新目录都将默认启用区分大小写。如图 6-13 所示。
图 6-13
使用/etc/wsl.conf [automount]部分来控制区分大小写
Windows 和 Linux 的互操作性
随着时间的推移,微软已经使 Linux 和 Windows 之间的文件系统互操作性越来越平滑,有时很难意识到这两个不同的操作系统是高度集成的,而不是孤立的,这弥合了它们之间的差距,使用户能够选择两个世界的最佳之处,并使用他们喜欢的东西,他们喜欢的地方,以及他们喜欢的方式。
从 Linux 访问 Windows 文件
安装在 Linux 的 Windows 子系统上的 drvfs 文件系统的主要作用是提供对 Windows 10 上的文件的访问,因此任何安装在 NT 文件系统上的固定驱动器都安装在 WSL 上。例如,NTFS 中的 C:\驱动器将在 WSL 中作为/mnt/c/提供,类似地,D:\作为/mnt/d/提供。
例如,如图 6-14 所示,我们可以使用ls
命令和路径/mnt/d/
图 6-14
使用 drvfs 文件系统从 WSL 访问 Windows 文件
此外,我们还可以读取这些 Windows 文件的内容,甚至使用我们最喜欢的 Linux 编辑器,如 nano,来编辑驻留在 Windows 10 上的 NT 文件系统中的文件,如图 6-15 所示。
图 6-15
使用 Linux 编辑器从 WSL 编辑 Windows NTFS 文件
WSL 还支持使用 Windows 应用访问 Linux 发行版中的文件。例如,我们可以使用 Windows 文件资源管理器(explorer.exe)从 WSL 控制台打开当前的工作目录。
正如您在下面的示例中看到的,我们能够在 explorer 中启动我们当前的工作目录,即/home/prateek/,作为基于 UNC 的共享路径\ \ wsl $ \ Ubuntu-18.04 \ home \ prateek \在图 6-16 中突出显示。在这里,我可以移动、编辑和执行各种文件操作,这些变化将反映到我们运行在 WSL 上的 Linux 发行版中。
图 6-17
使用 drvfs 文件系统将 Windows 文件复制到 WSL
图 6-16
从 WSL 为 Linux 文件使用 Windows Explorer.exe
像cp
这样用于复制文件的 Linux 命令可以与 drvfs 挂载一起使用,以访问 Windows NTFS 驱动器并将文件复制到 Linux 中,如图 6-17 所示。
或者如图 6-18 所示,使用mv
命令将文件或文件夹从 Windows 移动到 Linux 的 Windows 子系统。
最好的部分是 WSL 给了我们跨操作系统混合和匹配命令的能力,进一步缩小了 Linux 和 Windows 之间的差距。在图 6-19 所示的示例中,我使用了ipconfig.exe
(一个 Windows 可执行文件)从 WSL 中的 Windows 获取 IP 配置,然后使用grep
命令(一个 Linux 命令)过滤输出,然后再次使用 Linux 的 Windows 子系统上的 drvfs 挂载选项/mnt/
将带有所选结果的文件保存到 Windows NT 文件系统。我的意思是,这有多酷,而且很难找到这样一种融合两个世界优点的灵活性:
图 6-23
同时运行 WSL 和 Windows 命令
图 6-22
使用 Windows 中的\wsl$\在 WSL 上创建文件
图 6-21
使用\wsl$\访问特定的 Linux 发行版文件
图 6-20
访问 UNC 路径上的 Linux 分发文件系统:\wsl$\
图 6-19
在 Linux 命令中使用 Windows 可执行文件
图 6-18
使用 drvfs 文件系统将 Windows 文件移动到 WSL
ipconfig.exe | grep IPv4 > /mnt/d/ipaddress.txt
cat /mnt/d/ipaddress.txt
从 Windows 访问 Linux 文件
由于 Linux 文件系统的 Windows 子系统现在与 Windows 文件资源管理器(explorer.exe)高度集成,所有的 Linux 发行版都可以在一个特殊的 UNC 路径\wsl$\下获得,如图 6-20 所示。我可以在 Windows 文件资源管理器中看到所有的 Linux 发行版以及它们包含的文件和文件夹。
请注意,只有当 Linux 发行版启动并运行时,这些单独的 Linux 发行版包的路径才会出现。如果 Linux 发行版没有在 WSL 上运行,它就不会出现在\wsl$\ UNC 路径中。
因此,如果你想从 Windows 导航到 Ubuntu 文件系统,只需在文件资源管理器的地址栏中键入\wsl$\Ubuntu018.04\如图 6-21 所示,然后按回车键,它将带你到 Linux 文件系统的根目录。
可以访问这个\wsl\ UNC 路径将它们放在我的 Linux 发行版的主目录中,然后如果我们列出该文件夹中的项目,我们可以从 wsl 端看到两个文件的正确内容。
除此之外,您还可以使用 Linux 的 Windows 子系统来运行使用 wsl.exe 的命令,并将结果与像findstr
这样的 cmdlets 命令和像Select-String
这样的 PowerShell cmdlets 结合使用,以将两个世界混合在一起,如图 6-23 所示,从而提高用户效率并在一个地方获得两个世界的最佳效果。
摘要
在本章中,我们学习了文件系统组件,如 VFS、volfs、drvfs、tmpfs、procfs 和 sysfs,它们与 9P server 和多个 UNC 提供程序一起使 WSL1 文件系统成为可能;后来,我们研究了 WSL1 的文件系统架构,以及它与 WSL2 文件系统架构的不同之处,因为 WSL2 现在运行在一个轻量级实用虚拟机上,支持 Windows 10 附带的 Linux 内核。我们还看了几个例子,以了解在扩展属性的帮助下,区分大小写在 WSL 上是如何工作的,并且可以在目录或 drvfs 挂载级别上进行调整和控制。最后,我们以 WSL 提供的 Windows 和 Linux 互操作性结束了这一章,WSL 使用户能够从 Linux 运行 Windows 可执行程序,从 Windows 运行 Linux 应用,并允许高级用户轻松地混合和匹配这两个领域的最佳功能。在下一章中,我们将学习 WSl 网络,DNS 和网络接口是如何在 WSL 端组装的,以及 WSL1 和 WSL2 网络的区别。
七、网络连接
在本章中,我们将学习 Linux 的 Windows 子系统如何在子系统中配置网络,以及网络中的变化或更新如何从 Windows 端传播到 WSL。此外,我们将研究什么是 Linux 套接字,以及 WSL 如何实现它们,以便在 Windows 操作系统之上提供良好的 Linux 体验,同时保持互操作性。
今天,我们的计算机总是连接到网络和设备,我们需要通过网络堆栈持续访问互联网和其他系统,以交换数据、移动文件等,这进一步增加了网络作为任何软件应用成功背后的关键组件之一的重要性。
WSL 网络概述
让我们先简单概述一下如何在 Linux 上建立网络以及如何在 WSL 上实现网络,并让我们讨论一下为构建无缝兼容层以弥合 Windows 和 Linux 网络之间的差距而做出的设计选择。
网络接口和 DNS
Linux 使用通用系统调用来控制(读取和写入)任何设备,如网络接口,这种调用也称为输入/输出控制(IOCTL)。IOCTLs 使得查看连接到 Linux 的所有网络接口的列表成为可能,方法是通过这些系统调用来读取网络接口,并将这些信息保存在内核中。但是 WSL1 没有这种能力,因为没有可用的内核,我们实际上是在兼容层上使用 syscall 翻译在 Windows 上模拟 Linux。
为了弥补这一缺陷,一旦在 Windows 上启动了 WSL 实例,LXSS 管理器服务就会查询 Windows 操作系统上的网络接口列表,并将该列表传递给 WSL 驱动程序(lxcore.sys ),每当从 Linux 发行版发出系统调用(IOCTL)时,前面提到的缓存信息就会提供 WSL 中的网络接口列表。
在/etc/resolv.conf 文件中也会自动填充相同的列表,该文件是 Linux 上的解析器配置文件,包含 Windows 上配置的域名系统服务器列表。该文件中有许多配置选项可以使用,但默认情况下,它会创建一个通用配置:
nameserver <namer server IP address>
IP 地址可以是点符号表示的 IPv4 地址,也可以是点/冒号符号表示的 IPv6 地址,如图 7-1 所示。
图 7-1
WSL 上自动填充的解析程序文件
一些网络查询信息也会填充/etc/hosts 文件,也称为主机文件,其中包含一个主机名及其各自 IP 地址的静态查找表,如图 7-2 所示。/etc/resolv.conf
和/etc/hosts
的组合使得 DNS 支持在 Linux 的 Windows 子系统上成为可能。
图 7-2
WSL 上自动填充的主机文件
但是网络是一个非常动态的事物,事物变化非常快,例如,用户可以非常容易地从有线以太网切换到无线网络。WSL 中必须有一种机制来支持将这些更改从 Windows 更新到 WSL 中,因此 LXSS 管理器服务通过注册自身来接收与 Windows 端网络接口中的更新相关的任何通知,从而再次发挥作用。这意味着 LxssManager 服务正在监听任何更新通知,如果网络有变化,它将再次使用前述方法自动填充到 WSL 中,如图 7-3 所示。这使/etc/resolv.conf
和/etc/hosts
文件保持最新,并与 Windows 配置同步。
图 7-3
由于 Windows 环境的变化而重新配置的 WSL
图 7-3 演示了在步骤 3 中,当 Windows 端的网络接口被禁用时,以太网立即从 Linux 的 Windows 子系统中消失(通过步骤 4 中丢失的 MAC 地址验证),ICMP 请求在步骤 6 开始失败。
套接字
套接字是网络通信路径端点的抽象表示。套接字还可以作为本地非网络进程间通信的端点。在接下来的小节中,我们将简要介绍 Linux Berkeley sockets 和 Windows 操作系统中的类似实现 Winsock Kernel (WSK ),它使 WSL 能够将 Berkeley socket API 调用转换为 Winsock Kernel API 调用,反之亦然,从而使 Windows 和 Linux 之间的联网成为可能。
伯克利插座
在 Linux 中,Berkeley sockets(也称为 BSD sockets)是一个允许进程间通信(IPC)的 API 接口。为了建立通信,任何两个端点都要在它们的每一端打开一个套接字,然后该套接字被绑定到一个给定的地址,以便在它们之间发送或接收数据。
下面是一些常见的 BSD 套接字 API 函数。
插座( )
它用于创建特定类型的新套接字,打开套接字有三个要求,它们可以进一步用于对套接字进行分类:
-
地址族(AF)或域–套接字可以是这些域或地址族之一。
-
AF_INET 是互联网协议版本 4 (IPv4)的 Linux 实现。
-
AF_UNIX 也称为 AF_LOCAL,用于系统内的进程间通信。
-
AF_NETLINK 套接字用于用户模式和内核之间的通信,因为它们由用户空间进程的基于套接字的标准接口和内核模块的内部内核 API 组成。
-
-
套接字类型–套接字类型定义协议是面向连接的还是无连接的。
-
UDP 的 SOCK_DGRAM
-
TCP 的 SOCK_STREAM
-
ICMP 的 SOCK_RAW
-
-
套接字协议–协议参数可以设置为零“0”以请求协议的套接字类型的默认实现。
语法:
socket(AddressFamily, Type, Protocol);
示例:
socket(AF_INET, SOCK_STREAM, 0);
绑定( )
这个函数将一个套接字与一个套接字地址绑定在一起,即一个 IP 地址和一个端口号的组合。
听( )
此函数将指定的套接字标记为被动套接字,该套接字只接受传入的连接。
连接( )
该函数用于在引用的套接字和传递的 IP 地址之间建立连接。
send()、recv()、sendto()和 recvfrom()
顾名思义,这些函数用于通过套接字发送和接收数据。
关闭( )
该函数用于通过终止通过套接字建立的连接来释放系统资源。
Winsock 和 WSK (Winsock 内核)
Windows 操作系统具有前述 BSD 套接字的用户模式实现,称为“Winsock”,该实现非常相似但不完全相同,并且它不能在 Windows 子系统中用于 Linux,因为 WSL 的套接字实现是在内核模式中,即在 Linux 子系统的驱动程序库(WslSocket.lib)中。
为了解决这个挑战,WSL 中使用了另一个低级 Windows NT API,也称为 Winsock 内核(WSK)。WSK 是一个内核模式的网络编程接口,使用它,任何内核模式的软件都可以像用户模式的“Winsock”一样执行网络 I/O 操作基本上,Windows Subsystem for Linux 驱动程序将调用从 BSD 套接字 API 转换为 WSK API,并实现任何其他缺少的东西,以支持与本地 Linux 发行版几乎相同的网络体验。
如图 7-4 所示,当一个应用创建一个运行在 WSL 之上的 Linux 发行版中的 BSD 套接字时,BSD 套接字系统调用 WSL 的内核模式驱动程序 lxcore.sys,该驱动程序处理翻译。lxcore.sys 将这些 BSD 套接字系统调用转换为 WSK (Winsock 内核)可以理解的调用,它是 NT 内核中的一个低级 API,用于处理 Windows 操作系统上任何与套接字相关的请求,并将套接字连接到底层 TCP/IP 堆栈。
图 7-4
WSL 网络布局
WSL 与 WSL2 网络
Linux 版本 1 和 2 在 Windows 子系统中如何实现联网是完全不同的,了解其中的区别真的很重要;否则,你将陷入网络问题和意外行为。
其中一个主要区别是,在 WSL1 中,子系统使用与底层 Windows 操作系统相同的物理网络接口,因为其他一切都只是一个仿真,或者换句话说,是一个为支持 Windows 上的 Linux 发行版而构建的兼容层。这意味着您使用相同的网络接口卡(NIC)、IP 地址和 DNS 服务器。
但这在 WSL2 中发生了变化,因为在版本 2 中,Linux 的 Windows 子系统现在运行在使用 Hyper-V 构建的轻量级实用程序虚拟机上,就像任何虚拟机一样,WSL2 有自己专用的虚拟化网络接口,如图 7-5 所示,它有不同的 IP 地址和 DNS 服务器。
图 7-5
支持 WSL2 轻量级虚拟机的虚拟网络
除此之外,WSL1 和 WSL2 仍然填充/etc/resolv.conf
和/etc/hosts
文件以使 DNS 解析工作,除非这些文件被显式覆盖。
摘要
在本章中,我们学习了 Linux 的 Windows 子系统背后的网络概念,它使得 Windows 操作系统和 Linux 子系统之间的无缝体验和互操作性成为可能。我们讲述了网络接口以及如何在 WSL 上设置和配置名称解析,然后我们研究了 Berkeley sockets 和 Windows 中类似但不相同的实现 Winsock Kernel,它通过翻译 API 调用使 Linux 的 Windows 子系统中的联网成为可能。最后,我们讨论了 WSL1 和 WSL2 在联网方面的主要区别,wsl 1 模拟 Windows 上的 Linux 环境,wsl 2 是一个轻量级实用虚拟机,运行在 Windows 操作系统上,具有专用的网络接口。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2022-08-02 TensorFlow 深度学习实战指南中文版
2020-08-02 ApacheCN 数据科学译文集 2020.8