WSL 1 的入口点是什么?
What is the entry point for WSL 1?
假设我们有一个静态链接的 Linux 可执行文件。
我应该如何在导入的 tar.gz 中命名它,以便 WSL 1 默认情况下 运行 它在创建和启动时像:
# import an archive as a WSL distro
wsl --import static tmp-root-dir static.tar.gz
# boot distro to a default app??
wsl -d static
PS WSL 使用自己专有的启动进程,似乎不使用传统的 Unix /sbin/init
.
简答:
最小的可引导(无错误或警告)WSL rootfs 将包含三个文件:
/main
:您的 statically-linked 申请。只要名称与 passwd
. 中的名称相匹配,它就可以随意命名。
/etc/passwd
:定义为默认用户加载的应用程序(即shell)。
/etc/wsl.conf
:抑制正常的 WSL 功能并(可选)定义 non-root 用户。
更多详情:
这可能不完全您想要的,但它有望满足您的需求。
首先,WSL 的入口点(Linux ELF 二进制文件第一次在实例中启动)似乎是它的 /init
二进制文件,除了一些“ normal" Linux 初始化进程任务,设置一些 Windows-interop 功能。据我所知,目前无法更改。据我所知,对于 WSL1,它是在启动 WSL 实例时由 LXSS 管理器注入到实例中的。
注意:WSL2 在这方面可能 略有不同,因为它似乎确实使用 kernel-processed initrd 来加载 /init
。可以覆盖内核 command-line,但这会影响 所有 WSL2 实例,因此它可能不是一个实用的解决方案。
从你的问题中不太清楚你是否希望“默认应用程序”:
- 运行 作为默认 application/shell 每次
wsl -d static
是 运行,即使它已经是 运行ning.
- 或者在第一次启动 WSL1 实例时只 运行 一次。
我相信你正在寻找第一个选项。
运行 作为默认应用
在第一种情况下,标准的 WSL1 /init
流程可能会让您到达需要的位置。作为启动的一部分,如您所料,它读取 /etc/passwd
以确定要启动的用户 shell。它还读取 /etc/wsl.conf
以确定默认用户 ID(但如果在 wsl.conf
中没有设置默认用户,则回退到注册表)。
因此,要启动不同的应用程序(我们称之为 main
),您可以:
将二进制文件放在映像的根目录中。
在single-line/etc/passwd
:
中将应用设置为root用户的“shell”
user:x:1000:1000:user:/:/main
Side-note 这也将主目录设置为 /
因此我们不必创建另一个目录。
定义一个etc/wsl.conf
,内容如下:
[user]
default=user
[automount]
enabled=false
mountFsTab=false
[interop]
appendWindowsPath=false
这将阻止 WSL 执行以下启动任务,如果没有额外的图像支持,这会产生错误:
- 正在将 Windows 驱动器安装到实例中
- 正在尝试处理
/etc/fstab
(因为图像中没有 mount
命令)。
- 追加 Windows 路径(因为我们的实例无法访问 Windows 驱动器)
它还将默认用户设置为我们在 /etc/passwd
中创建的 UID 1000 用户。这不是绝对必要的 - 在这个 single-use 实例中,运行ning 作为 root 可能没有关系,但我已经将 non-root 用户作为“最佳实践”。
应该是这样。最小的可启动 WSL rootfs 将仅包含这三个文件:
/etc/wsl.conf
/etc/passwd
/main
这将适用于 WSL1 和 WSL2,但对于 WSL2,您应该使用 wsl ~ -d static
调用以确保它不会尝试在它可以启动的 Windows 驱动器上启动' 访问。否则,您将收到一个初始化错误,但您的应用程序仍将被调用。
运行一次
如果您正在寻找可以在实例首次启动时启动守护进程的东西,那么我在 . If you are on Windows 11, then there's a built-in mechanism via /etc/wsl.conf
. Otherwise, on Windows 10, you'll probably need to include some binary that can handle conditional logic. Something like execline 中记录的一些替代方案可能是完美的为此,但至少我在 WSL2 下遇到过问题,我不确定它是否会 运行 在 WSL1 下(但它可能)。
Side-note 对于 WSL1/musl
musl 是常用的替代 libc 实现。例如,Rust(AFAICT)只能使用 musl 生成真正的 statically-linked 可执行文件。但是请注意,WSL1 不能 运行 musl-based 静态链接二进制文件。
WSL2 可以很好地处理它们。
我设法让它工作了。最初我在创建 TAR 存档时错过了应用程序上的可执行位。
采用标准的 64 位汇编:
.data
msg:
.ascii "Hello, world!\n"
.set len, . - msg
.text
.globl _start
_start:
# write
mov , %rax
mov , %rdi
mov $msg, %rsi
mov $len, %rdx
syscall
# exit
mov , %rax
xor %rdi, %rdi
syscall
并创建一个最小的 WSL 系统:
wsl as -64 -o minimal.o minimal.s
wsl ld -melf_x86_64 -o minimal minimal.o
tar czf minimal.tar.gz \
--mode=a=rx \
--xform='s#^minimal#/[=11=]#' minimal
wsl --import minimal rootfs-minimal minimal.tar.gz --version 1
wsl --list
wsl -d minimal -e /minimal
要使可执行文件 默认(将 wsl -d minimal -e /minimal
缩短为 wsl -d minimal
),我们需要一个额外的文件 /etc/passwd
:
root:x:0:0:root:/root:/minimal
此文件的第一行 确定默认用户以及可执行文件(入口点)的路径,除非您使用 /etc/wsl.conf
:[=21= 覆盖用户]
[user]
default=user
基本上 WSL 1 只将 2 个文件视为魔法文件(除了忽略 /sbin/init
):
/etc/wsl.conf
/etc/passwd
假设我们有一个静态链接的 Linux 可执行文件。
我应该如何在导入的 tar.gz 中命名它,以便 WSL 1 默认情况下 运行 它在创建和启动时像:
# import an archive as a WSL distro
wsl --import static tmp-root-dir static.tar.gz
# boot distro to a default app??
wsl -d static
PS WSL 使用自己专有的启动进程,似乎不使用传统的 Unix /sbin/init
.
简答:
最小的可引导(无错误或警告)WSL rootfs 将包含三个文件:
/main
:您的 statically-linked 申请。只要名称与passwd
. 中的名称相匹配,它就可以随意命名。
/etc/passwd
:定义为默认用户加载的应用程序(即shell)。/etc/wsl.conf
:抑制正常的 WSL 功能并(可选)定义 non-root 用户。
更多详情:
这可能不完全您想要的,但它有望满足您的需求。
首先,WSL 的入口点(Linux ELF 二进制文件第一次在实例中启动)似乎是它的 /init
二进制文件,除了一些“ normal" Linux 初始化进程任务,设置一些 Windows-interop 功能。据我所知,目前无法更改。据我所知,对于 WSL1,它是在启动 WSL 实例时由 LXSS 管理器注入到实例中的。
注意:WSL2 在这方面可能 略有不同,因为它似乎确实使用 kernel-processed initrd 来加载 /init
。可以覆盖内核 command-line,但这会影响 所有 WSL2 实例,因此它可能不是一个实用的解决方案。
从你的问题中不太清楚你是否希望“默认应用程序”:
- 运行 作为默认 application/shell 每次
wsl -d static
是 运行,即使它已经是 运行ning. - 或者在第一次启动 WSL1 实例时只 运行 一次。
我相信你正在寻找第一个选项。
运行 作为默认应用
在第一种情况下,标准的 WSL1 /init
流程可能会让您到达需要的位置。作为启动的一部分,如您所料,它读取 /etc/passwd
以确定要启动的用户 shell。它还读取 /etc/wsl.conf
以确定默认用户 ID(但如果在 wsl.conf
中没有设置默认用户,则回退到注册表)。
因此,要启动不同的应用程序(我们称之为 main
),您可以:
将二进制文件放在映像的根目录中。
在single-line
中将应用设置为root用户的“shell”/etc/passwd
:user:x:1000:1000:user:/:/main
Side-note 这也将主目录设置为
/
因此我们不必创建另一个目录。定义一个
etc/wsl.conf
,内容如下:[user] default=user [automount] enabled=false mountFsTab=false [interop] appendWindowsPath=false
这将阻止 WSL 执行以下启动任务,如果没有额外的图像支持,这会产生错误:
- 正在将 Windows 驱动器安装到实例中
- 正在尝试处理
/etc/fstab
(因为图像中没有mount
命令)。 - 追加 Windows 路径(因为我们的实例无法访问 Windows 驱动器)
它还将默认用户设置为我们在
/etc/passwd
中创建的 UID 1000 用户。这不是绝对必要的 - 在这个 single-use 实例中,运行ning 作为 root 可能没有关系,但我已经将 non-root 用户作为“最佳实践”。
应该是这样。最小的可启动 WSL rootfs 将仅包含这三个文件:
/etc/wsl.conf
/etc/passwd
/main
这将适用于 WSL1 和 WSL2,但对于 WSL2,您应该使用 wsl ~ -d static
调用以确保它不会尝试在它可以启动的 Windows 驱动器上启动' 访问。否则,您将收到一个初始化错误,但您的应用程序仍将被调用。
运行一次
如果您正在寻找可以在实例首次启动时启动守护进程的东西,那么我在 /etc/wsl.conf
. Otherwise, on Windows 10, you'll probably need to include some binary that can handle conditional logic. Something like execline 中记录的一些替代方案可能是完美的为此,但至少我在 WSL2 下遇到过问题,我不确定它是否会 运行 在 WSL1 下(但它可能)。
Side-note 对于 WSL1/musl
musl 是常用的替代 libc 实现。例如,Rust(AFAICT)只能使用 musl 生成真正的 statically-linked 可执行文件。但是请注意,WSL1 不能 运行 musl-based 静态链接二进制文件。
WSL2 可以很好地处理它们。
我设法让它工作了。最初我在创建 TAR 存档时错过了应用程序上的可执行位。
采用标准的 64 位汇编:
.data
msg:
.ascii "Hello, world!\n"
.set len, . - msg
.text
.globl _start
_start:
# write
mov , %rax
mov , %rdi
mov $msg, %rsi
mov $len, %rdx
syscall
# exit
mov , %rax
xor %rdi, %rdi
syscall
并创建一个最小的 WSL 系统:
wsl as -64 -o minimal.o minimal.s
wsl ld -melf_x86_64 -o minimal minimal.o
tar czf minimal.tar.gz \
--mode=a=rx \
--xform='s#^minimal#/[=11=]#' minimal
wsl --import minimal rootfs-minimal minimal.tar.gz --version 1
wsl --list
wsl -d minimal -e /minimal
要使可执行文件 默认(将 wsl -d minimal -e /minimal
缩短为 wsl -d minimal
),我们需要一个额外的文件 /etc/passwd
:
root:x:0:0:root:/root:/minimal
此文件的第一行 确定默认用户以及可执行文件(入口点)的路径,除非您使用 /etc/wsl.conf
:[=21= 覆盖用户]
[user]
default=user
基本上 WSL 1 只将 2 个文件视为魔法文件(除了忽略 /sbin/init
):
/etc/wsl.conf
/etc/passwd