如果没有 systemd,WSL/WSL2/WSLg 如何工作?

如果没有 systemd,WSL/WSL2/WSLg 如何工作?

据我所知,systemd 是 Linux 的“主”守护进程,在启动后立即管理所有其他进程并运行其 init 函数。由于我遇到了这个(现已解决)问题,无法在 WSL 上使用任何 systemd 命令,我意识到它根本没有 systemd 进程。

现在,出于好奇,我想知道 WSL 依赖哪个进程管理而不是 systemd。由于我在“常规谷歌搜索”中没有找到令人满意的答案,所以我想,让我们在这里尝试一下。

答案1

更新: WSL2 现已提供 Systemd 支持(更新 #2)现在Windows 10 和 Windows 11。正如我最初的回答(见下文)和其他人在此处指出的那样,不是是必需的,并且可以选择加入。

Systemd 要求您使用更新的 WSL。请参阅我在 Ask Ubuntu 上的回答有关如何更新到最新版本并启用官方 Systemd 支持的详细信息。


原始答案仍然适用于 WSL 的运行方式:

好问题——这里有这么多有趣的东西可以讲!

首先,让我们先定义一些术语:

systemd 是 Linux 的“主”守护进程,启动后管理所有其他进程并运行其 init 功能。

首先,@mascoj 在评论中指出,Systemd 不是必需的Linux 根本不支持它。它当然在绝大多数 Linux 发行版中都使用,但也有其他替代方案(如@user1686 的回答提到)既早于 Systemd,又自其出现。一些发行版默认使用这些替代方案,并且(个人意见)其中一些发行版可能因此在 WSL 下运行得更好。

从高层次来看,Systemd 通常提供以下几个功能:

  • 初始化系统:执行启动时系统初始化(例如创建或清除临时文件等)
  • 启动时运行服务(例如,,,cron等等)sshdmariadb
  • PID 1 进程:所有其他进程都位于其下的主进程
  • 进程监控器(又名进程管理器):启动、监控、重启其他服务
  • 附加服务(Systemd 执行很多(例如伐木、坐骑等等)

这些功能中的大多数单独处理,但 Systemd“完成所有工作”。

一些发行版和系统不依赖 Systemd,并且执行起来不那么单一。例如,一些系统在启动期间的某个时刻让 init 系统将控制权移交给单独的进程管理器。进程管理器可能是 PID1,也可能不是。如果不是,那么通常 Init 进程仍为 PID1,进程管理器在其下运行。进程管理器通常有一个启动时所需的服务列表,它会执行和监视这些服务。

一些发行版(我想到了 Artix,而且我确信 Gentoo 也是如此)允许您混合搭配几个不同的 init 系统和进程管理器。


现在让我们从高层次来讨论标题中的问题:

如果没有 Systemd,WSL/WSL2/WSLg 如何工作?

  • WSL2:

    重要的是要理解,当你运行 WSL2 发行版时,该发行版并不在虚拟机中运行。WSL2本身正在运行具有其自己的发行版的虚拟机(可能水手-基于,如果我不得不猜测的话)。

    里面隐藏的虚拟机是您的发行版在其自己的命名空间集上运行的地方。如果您在 WSL2 中同时运行多个发行版,它们将全部在同一个虚拟机中运行,每个虚拟机都有自己的:

    • PID 命名空间
    • 挂载命名空间
    • IPC 命名空间
    • UTS 命名空间
    • WSLg 系统分发(仅限 Windows 11)

    但是,它们都与父 WSL2 VM 共享以下内容(因此彼此也共享):

    • 用户命名空间
    • 网络命名空间
    • Cgroup 命名空间
    • 设备树(除 以外/dev/pts
    • CPU/内核/内存/交换(显然)
    • /init二进制(但不是进程)

    这与 Docker 或 Podman(以及其他)等容器系统的工作方式非常非常相似。

    在大多数(但肯定不是全部)容器中,您很少会发现进程管理器正在运行。

    大多数容器由启动它们的“外部”进程(例如 Docker)告知要启动哪些服务。对于 WSL,传统上有一个wsl命令,用于告诉 WSL 要启动哪些服务。例如(一个过于简单且不一定很好的例子):

    wsl -e crond
    

    然而,一个重要的区别是,与传统容器不同,WSL 始终有自己的 Init 进程,该进程以 PID1 运行(原因见下文)。对于大多数其他容器类型,PID1 是你告诉它首先启动的进程。

  • WSL1

    虽然 WSL1 从技术上来说并不像 WSL2 那样“在容器/命名空间中运行”,但它确实共享相同的 Init 概念以实现互操作性。

    还需要记住的是,WSL1 并不支持所有 Linux 系统调用。当 WSL1 首次发布时,覆盖率大约为 70%。它在运行大量工具方面做得相当出色,但我觉得 Systemd 通常尝试启动的单元数量可能会暴露一些差距。

  • 世卫组织

    WSLg 在所谓的“系统发行版”中运行,这肯定是基于 Mariner 发行版的。每个尝试运行 GUI 应用程序的 WSL2 发行版都会创建一个 WSLg 系统发行版。

    在这种情况下,如何启动必要的服务实际上取决于微软。如果您愿意,您可以创建自己的系统发行版,微软提供了一个参考实现,但那里可能很少需要 Systemd 的功能。


这并不是说在 WSL(1 或 2)中运行进程管理器没有用处——在某些情况下确实有用。但就我个人而言,我很高兴 WSL 将这一决定权留给了用户。这使得它默认像容器一样运行(快速启动、高效使用资源),但在其他情况下更像(但不完全是)一个成熟的“虚拟操作系统”。


主要问题是:

现在,出于好奇,我想知道 WSL 依赖于哪个进程管理而不是 Systemd。

让我们将其分解为上面提到的 Systemd 处理的功能:

  • PID1/Init 系统:如上所述,WSL 的专有/init系统用于这两个功能。这个特殊功能/init是必需的,因为它处理 Linux 和 Windows 之间的深度互操作集成。传统的 Linux init 系统(如 Systemd)不知道如何处理这个问题。

    理论上,WSL2 可以使用 Systemd 来启动并设置一些特殊服务来处理集成,但是:

    • 这将给原本非常精简的初创企业增加开销

    • 有些发行版不使用 Systemd,因此他们必须对每个发行版进行不同的配置(如果需要,最好将此留给用户)。

    • 无论如何,可能/init仍然需要是 PID1,以便在启动后继续处理某些互操作功能。

      自 Systemd 以来需要PID1,这会产生一些冲突。我确实认为微软团队正在努力解决这个问题,但显然这个问题还没有得到解决。

  • 进程管理器/主管:WSL2 默认情况下确实没有进程管理器。但是,正如 @user1686 在另一个答案,直到最近这才成为一个问题。 脚本为每个服务创建了用于service启动/停止/重启/状态的命令(或类似命令)的入口点。

    至少 Ubuntu 仍然为服务提供许多此类脚本。因此,sshd例如,当您想要启动 时,只需运行sudo service ssh start,它就会调用其脚本。如果您安装 Maridb ( sudo service mysql start),情况也一样。

    然而,有些服务提供 SysVInit 样式的脚本。它们可能只提供 Systemd 单元,至少在基于 Systemd 的发行版上是如此。这些在 WSL 发行版上(很容易)无法工作。请参阅这个答案当这种情况发生时,我会介绍其他替代方案。

  • 启动时运行服务

    在 Windows 10 下,仍然没有很好的方法来处理这个问题。当然,WSL 发行版实际上并没有“启动”,但它确实有一个定义的“首次启动”,你可能想在其中运行某些东西。

    在 Windows 10 下,最好的方法是手动启动服务或通过用户启动文件运行它们(例如~/.bashrc)。请参阅这个答案了解一些这方面的想法。

    但听起来你使用的是 Windows 11(因为你提到了 WSLg),在这种情况下,此功能允许您指定在发行版启动时运行一次的命令(或一系列命令)。同样,请参阅这个答案有关如何配置的信息。

在启动时运行进程管理器

使用这些技术,完全可以运行您想要的任何进程管理器,只要它不要求它是 PID1。

到目前为止我在 WSL 上尝试过的一些方法:

  • 主管专为在容器中运行服务而设计。
  • 迪尼特- 可以用来阿蒂克斯,一个基于 Arch 的发行版,它有 5 种不同的 init/process manager 选项可供您使用。
  • s6,也适用于 Artix。这个在 WSL2 下有一些问题,我认为它们在 WSL2 方面,但我不确定。

s6 和 dinit 都倾向于认为它们在物理/虚拟机上运行(这是自然的),因此它们会尝试执行一些在 WSL 下不必要的启动。我已经能够删除不必要的项目,然后 dinit 至少运行得很好。不过,我还没有将这些内容汇总为一组可供其他人重现的说明。

运行 Systemd

甚至可以运行 Systemd,方法是将其伪装成在 WSL2(但不是 WSL1)发行版内的新命名空间中作为 PID1 运行(正如我们所讨论的,WSL1 已经在自己的命名空间中运行)。我个人不一定推荐它,但很多人都推荐。我在结尾处介绍了其中的一些内容这个 AU 答案,因此这里就不再重复了。

答案2

Systemd 实际上是一个相当新的项目,大约在 2010 年启动。在此之前已经使用过许多其他项目:sysvinit、upstart、init-ng、s6、launchd(我认为它曾经有一个 Linux 版本)。由于各种原因,一些 Linux 发行版仍然不使用 systemd。

在所有这些中,systemd 是最接近您甚至可以称为“进程管理器”。Linux 实际上根本不依赖进程管理器;任何进程都可以在它决定的时候直接创建(分叉)一个新的子进程,不受控制。(事实上,当 systemd 开始编纂诸如“注销应该杀死剩余进程”之类的东西时,人们为此而战。)

systemd 和其他类似程序的真正主要工作只是一个服务管理器:自动启动某些特定进程,例如负责显示登录屏幕的守护进程(GDM、agetty),有时在它们崩溃时重新启动它们。但是一旦您进入登录屏幕,其他一切都可以在没有 systemd/init 参与的情况下发生。

事实上,对于 sysvinit 来说,实际的 init 进程做的非常少:仅有的它所监督的服务是 agetty。实际上,其他一切都是通过普通的 shell 脚本完成的,这些脚本从未触及 init 本身。启动服务的命令是什么?Shell 脚本。所有的初始启动过程?运行更多 shell 脚本的 shell 脚本。

因此对于 WSL 之类的东西,没有想要像一个完整的系统一样运行(它不应该像一个完整的虚拟机那样,在使用之前必须启动;启动 WSL 应该是即时的,就像你真的在 Windows 上运行 Linux 应用程序一样),init 进程可以相当小。我真的不知道 WSL2 使用了什么,但它可以完全自定义。

(对于 WSL1 可能甚至没有一个 init 进程,因为 WSL1 甚至不是一个虚拟机,而只是一组仍然直接在 Windows 上运行的特殊进程。)

答案3

WSL 2 有一个自定义的 init 系统,它不是开源的(至少我没有找到源代码)。你可以使用ps或等工具查看它的进程htop

它是一个多调用二进制文件至少可以做到以下几点:

  • 运行 9p 服务器进行文件访问
  • 在 WSL 2 分发容器内启动 shell
  • 管理 WSL 2 分发容器
  • 运行其他互操作程序

您无法看到所有这些进程/守护程序,因为有些进程/守护程序在所有 WSL 2 容器之外运行(在根命名空间中)。

无论发行版中是否存在 init 系统,都不会使用。相反,shell 是使用配置的用户 ID 直接生成的。

答案4

Systemd 不是 Linux 的固有组成部分;许多 Linux 发行版都不使用它。无论你安装的 Linux 发行版使用什么,WSL 都会运行。

相关内容