# sysrc linux_enable="YES"
第 12 章 Linux 二进制兼容性
如果发现翻译错误,请直接 发起PR修改。
目录
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 服务将加载 Linux 应用程序所需的内核模块并挂载文件系统,这些文件系统位于 /compat/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 软件包中获取的 CentOS 基本系统
要安装 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.2. 使用 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 脚本挂载的文件系统在 chroots 或 jails 中的 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
如果在 ldd
输出的第一列中存在一个与 Linux 共享库的主要修订号匹配的库,则无需将其复制到最后一列中指定的文件中,因为现有库应该可以正常工作。但是,如果共享库是较新版本,则建议复制它。只要符号链接指向新的库,就可以删除旧的库。
例如,这些库已经存在于 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 包或port。安装完成后,root
用户可以使用以下命令来安装 .rpm 文件:
# cd /compat/linux
# rpm2cpio < /path/to/linux.archive.rpm | cpio -id
如果需要的话,对已安装的 ELF 二进制文件进行 brandelf
处理。请注意,这将阻止干净卸载。
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 中该文件不存在。如果没有配置名称服务器,请删除 bind
,使用 /etc/resolv.conf。
12.4.5. 杂项
有关 Linux® 与二进制兼容性的更多信息,请参阅文章 FreeBSD 中的 Linux 模拟。
上次修改时间: September 18, 2024 by fiercex