# 12.4.高级主题

所有与 Linux 相关的 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 控制项列表可以在 [linux(4)](https://man.freebsd.org/cgi/man.cgi?query=linux\&sektion=4\&format=html) 中找到。

某些应用程序需要挂载特定的文件系统。

这通常由 /etc/rc.d/linux 脚本处理，但可以通过执行以下命令在启动时禁用该脚本：

```sh
sysrc linux_mounts_enable="NO"
```

由 rc 脚本挂载的文件系统对于 chroot 或 jail 中的 Linux 进程无效；如有需要，请在 /etc/fstab 中进行配置：

```sh
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)](https://man.freebsd.org/cgi/man.cgi?query=debootstrap\&sektion=8\&format=html) 创建的基本系统子目录，请改为参照上文说明。

如果在配置好 Linux 二进制兼容层后某个 Linux 应用程序仍报告缺少共享库，请手动确定该 Linux 二进制程序所需的共享库并安装它们。

可以在使用相同 CPU 架构的 Linux 系统中使用 `ldd` 来确定该程序依赖哪些共享库。

例如，要查看 `linuxdoom` 所需的共享库，可在已安装 Doom 的 Linux 系统中运行以下命令：

```sh
% ldd linuxdoom
```

输出应类似如下：

```sh
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 系统上生成如下文件：

```sh
/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 系统上已有以下库：

```sh
/compat/linux/lib/libc.so.4.6.27
/compat/linux/lib/libc.so.4 -> libc.so.4.6.27
```

而 `ldd` 显示某个程序需要较新的版本：

```sh
libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29
```

由于已有的库版本只是在末尾小数字位相差一两个版本，该程序应仍然可以使用这个稍旧的版本。但更稳妥的做法是使用更新版本替换：

```sh
/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29
```

通常，在最初几次在 FreeBSD 上安装 Linux 程序时，才需要检查其依赖的共享库。随着系统上积累的 Linux 共享库越来越多，今后安装的新 Linux 程序通常就可以直接运行，无需额外处理。

## 12.4.2. 为 Linux ELF 可执行文件加标牌标识

FreeBSD 内核使用多种方式来判断一个待执行的可执行文件是否为 Linux 程序：它会检查 ELF 文件头中的标牌信息，查找已知的 ELF 解释器路径，并检查 ELF 注记；最后，默认情况下，如果一个 ELF 可执行文件没有标牌标识，也会被认为是 Linux 程序。

如果以上方法全部失败，尝试执行该程序时可能会出现如下错误信息：

```sh
% ./my-linux-elf-binary
```

输出可能如下：

```sh
ELF binary type not known
Abort
```

为了帮助 FreeBSD 内核区分 FreeBSD ELF 可执行文件与 Linux 可执行文件，可以使用 [brandelf(1)](https://man.freebsd.org/cgi/man.cgi?query=brandelf\&sektion=1\&format=html) 命令：

```sh
% brandelf -t Linux my-linux-elf-binary
```

## 12.4.3. 安装基于 Linux RPM 的应用程序

要安装基于 Linux 的 RPM 应用程序，首先安装软件包或 port [archivers/rpm4](https://cgit.freebsd.org/ports/tree/archivers/rpm4/) 。待安装完成，`root` 用户可以使用以下命令安装 `.rpm` 文件：

```sh
# cd /compat/linux
# rpm2cpio < /path/to/linux.archive.rpm | cpio -id
```

如有必要，请对安装后的 ELF 可执行文件使用 `brandelf`。注意，这样做将无法实现干净的卸载。

## 12.4.4. 配置主机名解析器

如果 DNS 无法使用，或者出现如下错误：

```sh
resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword
```

请按如下方式配置 `/compat/linux/etc/host.conf`：

```ini
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® 二进制兼容的工作机制，更多信息可参考文章 [Linux emulation in FreeBSD](https://docs.freebsd.org/en/articles/linux-emulation/)。
