# sysrc linux_enable="YES"
第 12 章. Linux 二进制兼容性
目录
12.1. 摘要
FreeBSD 提供了与 Linux® 的**可选**二进制兼容性,通常称为 Linuxulator,允许用户安装和运行未经修改的 Linux 二进制文件。它适用于 x86(32 位和 64 位)和 AArch64 架构。一些 Linux 特定的操作系统功能尚不支持;这主要发生在特定于硬件或与系统管理相关的功能上,例如 cgroups 或命名空间。
在阅读本章之前,您应该
了解如何安装其他第三方软件。
阅读完本章后,您将了解
如何在 FreeBSD 系统上启用 Linux 二进制兼容性。
如何安装额外的 Linux 共享库。
如何在 FreeBSD 系统上安装 Linux 应用程序。
FreeBSD 中 Linux 兼容性的实现细节。
12.2. 配置 Linux 二进制兼容性
默认情况下,linux(4) 二进制兼容性未启用。
要在启动时启用 Linux ABI,请执行以下命令
启用后,可以通过执行以下命令在不重启的情况下启动它
# service linux start
这足以使静态链接的 Linux 二进制文件工作。
Linux 服务将加载必要的内核模块,并在 /compat/linux 下挂载 Linux 应用程序预期的文件系统。它们可以像原生 FreeBSD 二进制文件一样启动;它们的行为几乎与原生进程完全相同,并且可以使用通常的方式进行跟踪和调试。
可以通过执行以下命令检查 /compat/linux 的当前内容
# ls -l /compat/linux/
输出应类似于以下内容
total 1 dr-xr-xr-x 13 root wheel 512 Apr 11 19:12 dev dr-xr-xr-x 1 root wheel 0 Apr 11 21:03 proc dr-xr-xr-x 1 root wheel 0 Apr 11 21:03 sys
12.3. Linux 用户空间
Linux 软件需要不仅仅是 ABI 才能工作。为了运行 Linux 软件,必须首先安装 Linux 用户空间。
如果只想运行 Ports 树中已包含的一些软件,可以通过包管理器安装,并且 pkg(8) 将自动设置所需的 Linux 用户空间。 例如,要安装 Sublime Text 4 及其依赖的所有 Linux 库,请运行以下命令
|
12.3.1. 来自 FreeBSD 包的 Rocky Linux 基础系统
要安装 Rocky Linux 9 用户空间,请执行以下命令
# pkg install linux_base-rl9
emulators/linux_base-rl9 将从 Rocky Linux 9 派生的基础系统放置到 /compat/linux 中。
安装软件包后,可以通过运行以下命令验证 /compat/linux 的内容,以检查是否已安装 Rocky Linux 用户空间
# ls -l /compat/linux/
输出应类似于以下内容
total 36 drwxr-xr-x 2 root wheel 512 Oct 9 17:28 afs lrwxr-xr-x 1 root wheel 7 May 16 2022 bin -> usr/bin drwxr-xr-x 3 root wheel 512 Oct 9 17:28 dev drwxr-xr-x 24 root wheel 1536 Oct 9 17:28 etc lrwxr-xr-x 1 root wheel 7 May 16 2022 lib -> usr/lib lrwxr-xr-x 1 root wheel 9 May 16 2022 lib64 -> usr/lib64 drwxr-xr-x 2 root wheel 512 Oct 9 17:28 opt drwxr-xr-x 2 root wheel 512 Oct 9 17:28 proc lrwxr-xr-x 1 root wheel 8 Oct 1 03:11 run -> /var/run lrwxr-xr-x 1 root wheel 8 May 16 2022 sbin -> usr/sbin drwxr-xr-x 2 root wheel 512 Oct 9 17:28 srv drwxr-xr-x 2 root wheel 512 Oct 9 17:28 sys drwxr-xr-x 8 root wheel 512 Oct 9 17:28 usr drwxr-xr-x 16 root wheel 512 Oct 9 17:28 var
12.3.2. 来自 FreeBSD 包的 CentOS 基础系统
由于上游项目的弃用,emulators/linux_base-c7 已被弃用。这意味着 emulators/linux_base-c7 将不会收到安全更新。除非需要 32 位兼容性,否则建议使用 Rocky Linux 基础系统。 |
要安装 CentOS 用户空间,请执行以下命令
# pkg install linux_base-c7
emulators/linux_base-c7 将从 CentOS 7 派生的基础系统放置到 /compat/linux 中。
安装软件包后,可以通过运行以下命令验证 /compat/linux 的内容,以检查是否已安装 CentOS 用户空间
# ls -l /compat/linux/
输出应类似于以下内容
total 30 lrwxr-xr-x 1 root wheel 7 Apr 11 2018 bin -> usr/bin drwxr-xr-x 13 root wheel 512 Apr 11 21:10 dev drwxr-xr-x 25 root wheel 64 Apr 11 21:10 etc lrwxr-xr-x 1 root wheel 7 Apr 11 2018 lib -> usr/lib lrwxr-xr-x 1 root wheel 9 Apr 11 2018 lib64 -> usr/lib64 drwxr-xr-x 2 root wheel 2 Apr 11 21:10 opt dr-xr-xr-x 1 root wheel 0 Apr 11 21:25 proc lrwxr-xr-x 1 root wheel 8 Feb 18 02:10 run -> /var/run lrwxr-xr-x 1 root wheel 8 Apr 11 2018 sbin -> usr/sbin drwxr-xr-x 2 root wheel 2 Apr 11 21:10 srv dr-xr-xr-x 1 root wheel 0 Apr 11 21:25 sys drwxr-xr-x 8 root wheel 9 Apr 11 21:10 usr drwxr-xr-x 16 root wheel 17 Apr 11 21:10 var
12.3.3. 使用 debootstrap 的 Debian/Ubuntu 基础系统
提供 Linux 共享库的另一种方法是使用 sysutils/debootstrap。这具有提供完整 Debian 或 Ubuntu 发行版的优势。
要安装 debootstrap,请执行以下命令
# pkg install debootstrap
debootstrap(8) 需要启用 linux(4) ABI。启用后,请执行以下命令以在 /compat/ubuntu 中安装 Ubuntu 或 Debian
# debootstrap focal /compat/ubuntu
虽然从技术上讲可以安装到 /compat/linux 中,但由于可能与基于 CentOS 的软件包发生冲突,因此不建议这样做。相反,从发行版或版本名称派生目录名称,例如 /compat/ubuntu。 |
输出应类似于以下内容
I: Retrieving InRelease I: Checking Release signature I: Valid Release signature (key id F6ECB3762474EDA9D21B7022871920D1991BC93C) I: Retrieving Packages I: Validating Packages I: Resolving dependencies of required packages... I: Resolving dependencies of base packages... I: Checking component main on http://archive.ubuntu.com/ubuntu... [...] I: Configuring console-setup... I: Configuring kbd... I: Configuring ubuntu-minimal... I: Configuring libc-bin... I: Configuring ca-certificates... I: Base system installed successfully.
然后在 /etc/fstab 中设置挂载点。
如果应共享主目录的内容并能够运行 X11 应用程序,则应使用 nullfs(5) 进行循环回送,将 /home 和 /tmp 挂载到 linux 兼容区域。 以下示例可以添加到 /etc/fstab # Device Mountpoint FStype Options Dump Pass# devfs /compat/ubuntu/dev devfs rw,late 0 0 tmpfs /compat/ubuntu/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0 fdescfs /compat/ubuntu/dev/fd fdescfs rw,late,linrdlnk 0 0 linprocfs /compat/ubuntu/proc linprocfs rw,late 0 0 linsysfs /compat/ubuntu/sys linsysfs rw,late 0 0 /tmp /compat/ubuntu/tmp nullfs rw,late 0 0 /home /compat/ubuntu/home nullfs rw,late 0 0 然后执行 mount(8)
|
要使用 chroot(8) 访问系统,请执行以下命令
# chroot /compat/ubuntu /bin/bash
然后可以执行 uname(1) 以检查 Linux 环境
# uname -s -r -m
输出应类似于以下内容
Linux 3.17.0 x86_64
进入 chroot 后,系统行为与正常的 Ubuntu 安装相同。虽然 systemd 不起作用,但 service(8) 命令照常工作。
要添加默认情况下缺少的软件包存储库,请编辑文件 /compat/ubuntu/etc/apt/sources.list。 对于 amd64,可以使用以下示例 deb http://archive.ubuntu.com/ubuntu focal main universe restricted multiverse deb http://security.ubuntu.com/ubuntu/ focal-security universe multiverse restricted main deb http://archive.ubuntu.com/ubuntu focal-backports universe multiverse restricted main deb http://archive.ubuntu.com/ubuntu focal-updates universe multiverse restricted main 对于 arm64,可以使用以下示例 deb http://ports.ubuntu.com/ubuntu-ports bionic main universe restricted multiverse |
12.4. 高级主题
某些应用程序需要挂载特定的文件系统。
这通常由 /etc/rc.d/linux 脚本处理,但可以通过执行以下命令在启动时禁用
sysrc linux_mounts_enable="NO"
rc 脚本挂载的文件系统对 chroot 或 jail 中的 Linux 进程不起作用;如果需要,请在 /etc/fstab 中配置它们
devfs /compat/linux/dev devfs rw,late 0 0 tmpfs /compat/linux/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0 fdescfs /compat/linux/dev/fd fdescfs rw,late,linrdlnk 0 0 linprocfs /compat/linux/proc linprocfs rw,late 0 0 linsysfs /compat/linux/sys linsysfs rw,late 0 0
由于 Linux 二进制兼容性层已获得对运行 32 位和 64 位 Linux 二进制文件的支持,因此不再可能将模拟功能静态链接到自定义内核中。
12.4.1. 手动安装其他库
对于使用 debootstrap(8) 创建的基础系统子目录,请改用上述说明。 |
如果在配置 Linux 二进制兼容性后,Linux 应用程序抱怨缺少共享库,请确定 Linux 二进制文件需要哪些共享库并手动安装它们。
在使用相同 CPU 架构的 Linux 系统中,可以使用 ldd
确定应用程序需要哪些共享库。
例如,要检查 linuxdoom
需要哪些共享库,请在已安装 Doom 的 Linux 系统中运行以下命令
% ldd linuxdoom
输出应类似于以下内容
libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0 libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0 libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29
然后,将输出最后一列中的所有文件从 Linux 系统复制到 FreeBSD 系统上的 /compat/linux 中。复制完成后,创建指向第一列中名称的符号链接。
此示例将在 FreeBSD 系统上生成以下文件
/compat/linux/usr/X11/lib/libXt.so.3.1.0 /compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0 /compat/linux/usr/X11/lib/libX11.so.3.1.0 /compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0 /compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -> libc.so.4.6.29
如果 Linux 共享库已存在且主修订号与 ldd
输出的第一列匹配,则无需将其复制到最后一列中命名的文件,因为现有库应该可以工作。不过,如果它是较新版本,建议复制共享库。可以删除旧的库,只要符号链接指向新的库即可。
例如,这些库已存在于 FreeBSD 系统上
/compat/linux/lib/libc.so.4.6.27 /compat/linux/lib/libc.so.4 -> libc.so.4.6.27
并且 ldd
指示二进制文件需要较新版本
libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29
由于现有库在最后一位数字上仅落后一两个版本,因此程序仍然可以使用稍旧的版本。但是,用较新版本替换现有的 libc.so 是安全的
/compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -> libc.so.4.6.29
通常,只需要在 FreeBSD 上首次安装 Linux 程序时查找 Linux 二进制文件依赖的共享库。一段时间后,系统上将有一组足够的 Linux 共享库,能够在无需任何额外工作的情况下运行新安装的 Linux 二进制文件。
12.4.2. 标记 Linux ELF 二进制文件
FreeBSD 内核使用多种方法来确定要执行的二进制文件是否是 Linux 二进制文件:它检查 ELF 文件头中的品牌,查找已知的 ELF 解释器路径并检查 ELF 注记;最后,默认情况下,未标记的 ELF 可执行文件被假定为 Linux 可执行文件。
如果所有这些方法都失败,则尝试执行二进制文件可能会导致错误消息
% ./my-linux-elf-binary
输出应类似于以下内容
ELF binary type not known Abort
为了帮助 FreeBSD 内核区分 FreeBSD ELF 二进制文件和 Linux 二进制文件,请使用 brandelf(1)
% brandelf -t Linux my-linux-elf-binary
12.4.3. 安装基于 Linux RPM 的应用程序
要安装基于 Linux RPM 的应用程序,首先安装 archivers/rpm4 软件包或端口。安装完成后,root
可以使用此命令安装 .rpm
# cd /compat/linux
# rpm2cpio < /path/to/linux.archive.rpm | cpio -id
如有必要,请使用 brandelf
标记已安装的 ELF 二进制文件。请注意,这将阻止干净卸载。
12.4.4. 配置主机名解析器
如果 DNS 不工作或出现此错误
resolv+: "bind" is an invalid keyword resolv+: "hosts" is an invalid keyword
请如下配置 /compat/linux/etc/host.conf
order hosts, bind multi on
这指定首先搜索 /etc/hosts,然后搜索 DNS。当 /compat/linux/etc/host.conf 不存在时,Linux 应用程序使用主机系统中的 /etc/host.conf,但它们会报错,因为该文件在 FreeBSD 中不存在。如果未使用 /etc/resolv.conf 配置名称服务器,请删除 bind
。
12.4.5. 其他
有关 Linux® 二进制兼容性如何工作的更多信息,请参阅文章 FreeBSD 中的 Linux 模拟。
最后修改时间:2024 年 10 月 13 日,作者 Fernando Apesteguía