22.2. 安装

默认的Linux兼容模式没有被打开。启用这个功能的最容易的方法是调用linux KLD对象(“Kernel LoaDable object”)。你可以在命令行通过健入linux来加载这个模块。

如果你想让Linux二进制兼容性总是被启用,你可以在/etc/rc.conf加入下面这一行:

linux_enable="YES"

kldstat(8)可以用来检查KLD模块是否加载:

% kldstat
Id Refs Address    Size     Name
 1    2 0xc0100000 16bdb8   kernel
 7    1 0xc24db000 d000     linux.ko

如果你不想或者无法将Linux KLD加载,你就需要在内核中静态链接进Linux二进制兼容模式。你必须在 你的内核配置文件里面加入options LINUX,然后按照Chapter 9重新编译内核。

22.2.1. 安装Linux运行时库

有两种方法来安装Linux运行时库,要么使用linux_base port, 要么手动安装。

22.2.1.1. 使用linux_base Port安装

这是最容易的安装方法,只需要像安装其他port一样从 ports collection来安装:

# cd /usr/ports/emulators/linux_base
# make install distclean

你现在应当是工作在Linux兼容模式下了。一些程序可能会提示系统库的版本不正确。通常,这不是问题。

Note: 有多个版本的emulators/linux_base port,针对不同的版本的Linux。 你应该选择最接近Linux应用程序需要的那个版本来安装。

22.2.1.2. 手动安装

如果你没有安装“ports” collection,你也可以通过手动来安装Linux运行时库。 你将需要这些程序依赖的Linux共享库,而且你需要创建一个“shadow root” 目录/compat/linux,任何要被Linux程序打开的共享库都首先在这个目录里面查找。 所以,如果一个Linux程序加载了,例如,/lib/libc.so,FreeBSD 会首先尝试打开 /compat/linux/lib/libc.so,如果不存在,它将尝试打开/lib/libc.so。 共享库应该安装在/compat/linux/lib而不是Linux ld.so报告的其他路径。

通常,你需要寻找Linux程序依赖的共享库。然后, 你需要在系统上做一个高效的Linux共享库设置,以便能够运行最新的Linux程序。

22.2.1.3. 如何安装额外的共享库

如果你安装了linux_base port,但是你的 你的应用程序仍会报告丢失共享库的信息?你如何知道Linux程序需要哪个共享库? 基本上,有两种可能性(接下来的指令需要root权限):

如果你有可以访问的Linux系统, 看看应用程序需要什么共享库, 把它们拷贝到你的FreeBSD系统。看下面的例子:

我们假设你通过FTP得到Linux程序Doom, 并把它放在你能访问的Linux系统上。然后你可以通过ldd linuxdoom来检查需要哪些共享库, 就像这样:

% 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

你需要得到上面输出的右列的所有文件,并把他们拷贝到/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

Note: 如果你已经有了一个与ldd 输出的第一列的主修订号相匹配的Linux共享库, 你将不需要把右列命名的文件拷贝到你的系统,你已经完成了工作。 如果有一个新的版本,那无论如何都要拷贝一个共享库。 你可以删掉旧的,你只要做一个符号连接到新的版本。 所以,如果有这些库在你的系统上:

/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

如果结尾的数字只有一到两个版本过期,那也不要担心拷贝/lib/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

Note: 符号链接机制仅仅是Linux程序需要的。 FreeBSD的运行时连接器会自己寻找匹配的主修订号,你不需要为此担心。

22.2.2. 安装Linux ELF程序

ELF格式的程序需要一步额外的步骤“标记”。如果你尝试运行没有标记的ELF程序, 你会得到像下面这样的错误信息:

% ./my-linux-elf-binary
ELF binary type not known
Abort

为了帮助FreeBSD内核分辨FreeBSD ELF程序和Linux程序,要使用brandelf(1)工具:

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

GNU工具现在会自动把适当的标记信息放到ELF程序中,你以后遇到这个问题的机会越来越少。

22.2.3. 配置主机名解析器

如果DNS不能正常工作或是你得到下列信息:

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

你就需要配置/compat/linux/etc/host.conf文件,此文件包含:

order hosts, bind
multi on

order这一行指出/etc/hosts先被搜索再接着搜索DNS。 如果/compat/linux/etc/host.conf没有被安装,Linux程序会读取FreeBSD的 /etc/host.conf然后提示不兼容的FreeBSD语法。 如果你没有使用/etc/resolv.conf 文件设置DNS,应该删除bind