linux的windows子系统WSL1的入口点是什么



假设我们有一个静态链接的Linux可执行文件。

我应该如何在导入的tar.gz中命名它,以便WSL1在创建和启动时默认运行它,如:

# 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

PSWSL使用自己的专有引导过程,似乎不使用传统的Unix/sbin/init

简短回答:

最小的可引导(没有错误或警告)WSL rootfs将由三个文件组成:

  • /main:静态链接的应用程序。只要名称与passwd中的名称相匹配,就可以随心所欲地命名它
  • /etc/passwd:定义要为默认用户加载的应用程序(即shell)
  • /etc/wsl.conf:抑制正常的WSL功能并(可选)定义非根用户

更多详细信息:

这可能不是你想要的,但它有望满足你的需求。

首先,WSL(第一次在实例中启动Linux ELF二进制文件)的入口点似乎是它的/init二进制文件,除了一些";正常的";Linux初始化进程任务,设置一些Windows互操作功能。据我所知,目前无法改变。据我所知,对于WSL1,它是由LXSS管理器在启动WSL实例时注入到实例中的。

注意:WSL2在这方面可能略有不同,因为它似乎确实使用了内核处理的initrd来加载/init。可以覆盖内核命令行,但这会影响所有WSL2实例,因此这可能不是一个实用的解决方案。

从你的问题中还不太清楚你是否想要";默认应用程序";至:

  • 每次运行wsl -d static时作为默认应用程序/shell运行,即使它已经在运行
  • 或者在第一次启动WSL1实例时只运行一次

我相信你正在寻找第一种选择。

作为默认应用程序运行

在第一种情况下,标准的WSL1/init进程可能会让您到达需要的位置。正如您所期望的,作为启动的一部分,它读取/etc/passwd以确定要启动的用户shell。它还读取/etc/wsl.conf以确定默认用户ID(但如果wsl.conf中没有设置默认用户,则返回注册表)。

因此,要启动一个不同的应用程序(让我们称之为main),您可以:

  • 将二进制文件放在映像的根目录中。

  • 将应用程序设置为";外壳;根用户的单行/etc/passwd:

    user:x:1000:1000:user:/:/main
    

    需要注意的是,这还将主目录设置为/,这样我们就不必创建另一个目录。

  • 定义具有以下内容的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用户。这并不是绝对必要的——在这个一次性实例中以root用户身份运行可能没有什么问题,但我已经将一个非root用户作为"root"用户包括在内;最佳实践";。

应该是这样。最小的可引导WSL rootfs将仅由以下三个文件组成:

/etc/wsl.conf
/etc/passwd
/main

这将适用于WSL1和WSL2,尽管对于WSL2,您应该使用wsl ~ -d static进行调用,以确保它不会试图在无法访问的Windows驱动器上启动。否则,您将收到一个init错误,但您的应用程序仍将被调用。

运行一次

例如,如果您正在寻找能够在实例第一次启动时启动守护进程的东西,那么我在这个答案中记录了一些替代方案。如果你使用的是Windows 11,那么有一个通过/etc/wsl.conf的内置机制。否则,在Windows10上,您可能需要包含一些可以处理条件逻辑的二进制文件。像execline这样的东西可能非常适合这一点,但至少我在WSL2下遇到过问题,我不确定它是否会在WSL1下运行(但它可能)。

WSL1/musl的旁注

musl是一种常用的替代libc实现。例如,Rust(AFAICT)只能使用musl生成真正静态链接的可执行文件。但是,请注意,WSL1不能运行基于musl的静态链接二进制文件。

WSL2可以很好地处理它们。

我设法让它工作起来。最初,在创建TAR档案时,我错过了应用程序上的一个可执行部分。

以标准64位组件为例:

.data
msg:
.ascii "Hello, world!n"
.set len, . - msg
.text
.globl _start
_start:
# write
mov  $1,   %rax
mov  $1,   %rdi
mov  $msg, %rsi
mov  $len, %rdx
syscall
# exit
mov  $60, %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#/#' 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:覆盖用户

[user]
default=user

基本上,WSL1只将2个文件视为神奇的(除了忽略/sbin/init之外):

  • /etc/wsl.conf
  • /etc/passwd

最新更新