关于Windows子系统(WSL/WSL2)的一些探究
关于Windows子系统(WSL/WSL2)的一些探究
目前博主日常工作已经离不开WSL了,但是即使每天使用,对WSL系统的一些细节上的实现还是一知半解,为此,特地去了解了一番,并做一下记录,方便日后查阅。
Windows WSL1 和 WSL2的网络机制及各自的原理
-
实现机制差异
WSL1 和 WSL2 的网络机制的主要区别在于,WSL1 是通过一个转换层来实现对 Linux 系统调用的支持,而 WSL2 是通过在轻量级虚拟机内运行一个实际的 Linux 内核来实现完整的系统调用兼容性。 -
不用的网络方式
- 从 Windows 访问 WSL2 网络应用时,可以使用
localhost
作为 IP 地址,就像访问本地应用一样。 - 从 WSL2 访问 Windows 网络应用时,需要使用主机的 IP 地址,可以通过在 Linux 分发版中运行
cat /etc/resolv.conf
命令来获取。 - 从局域网 (LAN) 访问 WSL2 分发版时,需要添加一个端口代理来将主机上的端口映射到 WSL2 的 IP 地址和端口。
- 从 Windows 访问 WSL2 网络应用时,可以使用
-
WSL1 和 WSL2 的网络机制的原理是:
- WSL1 是通过一个转换层来拦截 Linux 系统调用,并将其转换为 Windows 系统调用,从而实现对 Linux 应用的支持。这样,WSL1 可以直接使用 Windows 的网络栈和 IP 地址,无需额外的配置。
- WSL2 是通过 Hyper-V 功能来创建一个轻量级虚拟机,并在其中运行一个完整的 Linux 内核,从而实现对 Linux 应用的支持。这样,WSL2 就有了自己的虚拟化以太网适配器和 IP 地址,与 Windows 的网络栈是隔离的。为了实现 Windows 和 Linux 之间的网络互通,WSL2 使用了一种叫做
Plan9
协议的技术,来在虚拟机和主机之间共享文件和端口。
目前尚未支持WSL直接访问纯ipv6网络
性能:WSL1 vs WSL2
WSL1 和 WSL2 在性能方面的区别主要体现在以下几个方面:
- 文件系统性能:WSL2 在文件密集型操作(如 git 克隆、npm 安装、apt 更新等)上比 WSL1 快很多,因为它使用了一个真正的 Linux 文件系统,而不是通过转换层来访问 Windows 文件系统。
- 系统调用兼容性:WSL2 支持完全的系统调用兼容性,可以运行更多的 Linux 应用,例如 Docker 等,而 WSL1 只能支持一部分系统调用,有些应用可能无法正常工作。
启动时间和资源占用:WSL1 和 WSL2 都有较短的启动时间和较少的资源占用,相比传统的虚拟机体验更加轻量级和快速。 - 跨操作系统文件访问:WSL1 可以更快地访问从 Windows 装载的文件,而 WSL2 需要通过
Plan9
协议来共享文件和端口,因此在跨操作系统的文件访问上性能会有所下降。 - 内存管理:WSL2 的内存使用量会随使用而缩放,并且在进程释放内存时会自动返回到 Windows。但是,WSL2 目前还不会在关闭实例前将内存中缓存的页面释放回 Windows,这可能会导致 Windows 内存耗尽。
在 Windows 上安装和使用 WSL2
在 Windows 上安装和使用 WSL2 的方法有:
- 使用单个命令:在管理员模式下打开 PowerShell 或 Windows 命令提示符,输入
wsl --install
命令,然后重启计算机。这样会启用 WSL 功能并安装 Ubuntu 发行版。 - 使用手动步骤:首先启用 WSL 功能和虚拟机平台功能,然后下载 Linux 内核更新包,再设置 WSL2 为默认版本,最后从 Microsoft Store 中选择并安装 Linux 发行版。
安装好 WSL2 后,可以使用 wsl 命令来管理和使用 Linux 发行版,例如:
wsl -l -v
: 列出已安装的 Linux 发行版和它们的 WSL 版本wsl -d <distro name>
: 运行指定的 Linux 发行版wsl --set-version <distro name>
2 : 将指定的 Linux 发行版升级到 WSL2wsl --shutdown
: 关闭所有运行的 Linux 发行版
还可以使用 Windows 终端、VS Code、Docker Desktop 等工具来增强 WSL2 的体验。
在 WSL 中安装和使用 Docker(仅WSL2支持)
在 WSL 中安装和使用 Docker 有两种方式,一种是在 WSL2 中直接安装原生的 Linux 版 Docker,另一种是在 Windows 中安装 Docker Desktop for Windows,并启用基于 WSL2 的引擎。
第一种方式的步骤如下:
- 在 WSL2 中安装喜欢的 Linux 发行版,例如 Ubuntu,并更新系统和软件源。
在 Linux 发行版中运行curl -fsSL https://get.docker.com -o get-docker.sh
命令,下载 Docker 的安装脚本。 - 运行
sudo sh get-docker.sh
命令,执行安装脚本。注意,脚本会提示使用 Docker Desktop for Windows,可以忽略这个提示,等待 20 秒后继续安装。 - 运行
sudo service docker start
命令,启动 Docker 服务。 - 运行
docker --version
命令,检查 Docker 的版本和内部版本号。 - 运行
docker run hello-world
命令,测试安装是否正常工作。
第二种方式的步骤如下:
- 在 Windows 中下载并安装 Docker Desktop for Windows。
- 启动 Docker Desktop for Windows,并从任务栏的隐藏图标菜单中选择 Docker 图标。
- 右键单击该图标以显示 Docker 命令菜单,然后选择“设置”。
- 确保在“设置”>“常规”中选中“使用基于 WSL2 的引擎”。
- 通过转到“设置”>“资源”>“WSL 集成”,从要启用 Docker 集成的已安装 WSL2 发行版中进行选择。
- 重启 Docker Desktop for Windows,重启完成后即可在 WSL2 中使用 docker 命令了。
无论使用哪种方式,在 WSL 中安装和使用 Docker 都需要计算机支持 WSL2,并且已经开启了虚拟化功能。
Docker Desktop使用WSL2
作为后端与Hyper-V
后端的性能说明
- WSL2 使用了一个完整的 Linux 内核,可以直接运行 Linux 的二进制文件,而不需要模拟或转换系统调用,这样可以提高执行效率和兼容性。
- WSL2 使用了动态内存分配的特性,可以根据需要调整 docker 的 CPU 和内存资源,而不需要预先分配固定的资源。这样可以减少资源的浪费和竞争,提高容器的启动速度和运行速度。
- WSL2 使用了一个虚拟化的以太网适配器,可以实现 Windows 和 Linux 之间的高速网络通信,而不需要通过 NAT 或端口映射。这样可以提高网络的性能和稳定性。
对应两种方式在WSL2里安装docker,把运行的容器的端口暴露到Windows的方法
WSL2原生安装Docker
- 配置端口转发规则的一般步骤是:
- 在 Windows 防火墙中开放要转发的端口,例如
22
,80
等。 - 在 PowerShell 中以管理员身份运行
netsh interface portproxy add v4tov4
命令,指定监听端口,监听地址,连接端口和连接地址。 - 监听地址可以设置为
0.0.0.0
,表示匹配所有地址。 - 连接地址可以设置为
localhost
或者 WSL2 的 IP 地址。 - 连接端口应该和容器启动时指定的端口映射一致,例如
-p 80:80
。
- 在 Windows 防火墙中开放要转发的端口,例如
举例:如果想从局域网的其他主机上通过 ssh
连接到 WSL2 里的 docker 容器,需要在 Windows 中执行以下命令:
netsh interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=localhost |
这样就可以将 Windows 的 22
端口转发到 WSL2 的 22
端口,然后就可以使用的 Windows 的 IP 地址和 22
端口来 ssh 连接到 WSL2 里的 docker 容器了。
查看或删除已经配置的端口转发规则,可以在 PowerShell 中运行以下命令:
netsh interface portproxy show all # 查看所有规则 |
这是因为 WSL2 使用了一个虚拟化的以太网适配器,它有自己的 IP 地址,和 Windows 不在同一个网络。
安装Docker Desktop并选用WSL2作为backend
在 WSL2 里安装的 Docker 容器,可以通过 localhost
或者 Windows 的 IP 地址来访问,只要在 Windows 中开启了防火墙的相应端口,并且在 Docker 容器中也指定了相应的端口映射。
例如,在 WSL2 中运行了一个 web 服务,监听了 80
端口,可以在 Windows 中打开浏览器,输入 localhost 或者的 Windows 的 IP 地址(可以通过 ipconfig
命令查看),就可以访问到这个 web 服务。
Docker Desktop for Windows 通过在 Windows 和 WSL2 之间建立端口转发规则,使得可以直接通过 localhost 或者 Windows 的 IP 地址来访问容器端口。
在 WSL 中配置网络代理
在 WSL 中配置网络代理的方法有多种,根据使用的代理软件和协议的不同,可能需要不同的步骤。一般来说,需要做以下几件事:
- 在 Windows 中找到的代理软件的监听端口和 IP 地址,通常是
127.0.0.1
或者的本机 IP 地址。 - 在 Windows 中打开防火墙设置,允许的代理软件和 WSL 之间的网络通信。
- 在 Windows 中启用“允许来自局域网的连接”或者类似的选项,让的代理软件接受来自 WSL 的请求。
- 在 WSL 中设置环境变量,例如
http_proxy
、https_proxy
、all_proxy
等,指向的代理软件的监听端口和 IP 地址。注意,如果使用的是 WSL2,那么不能使用127.0.0.1
来指向 Windows,而要使用的本机 IP 地址或者 WSL 的网关地址(可以通过cat /etc/resolv.conf
命令查看)。 - 在 WSL 中测试的代理配置是否生效,例如使用
curl
、apt
、git
等命令。
为docker容器配置全局代理
全局配置:在 docker 客户端的配置文件 ~/.docker/config.json
中添加 proxies 字段,指定 httpProxy
、httpsProxy
、noProxy
等代理信息。这样在创建或启动新的容器时,代理信息会自动传递给容器。这种方法需要 docker 17.07 或更高版本。
为docker容器单独配置代理
单独配置:在创建或运行容器时,使用 --env
或 -e
标志,设置 HTTP_PROXY
、HTTPS_PROXY
、FTP_PROXY
、NO_PROXY
等环境变量,指定代理信息。这种方法可以针对不同的容器设置不同的代理。
总结
相信看完这篇文章,你和我一样,会对Windows的WSL有一个更深入的理解,一起Mark!