11.3. 高级主题
上一页 | 第 11 章 Linux® 二进制兼容模式 | 下一页

## 11.3. 高级主题

此章节将讲述是 Linux® 二进制兼容如何工作的， 内容基于 Terry Lambert `<tlambert@primenet.com>` (Message ID: `<199906020108.SAA07001@usr09.primenet.com>`) 发表在 FreeBSD 闲聊邮件列表 的邮件。

FreeBSD 有一个叫 “execution class loader” 的抽象层。 它被嵌入进了 execve(2) 系统调用。

历史上 UNIX® 加载器会依靠查看魔数 （通常是文件的开头 4 至 8 个字节）来确认是否是系统已知的的二进制程序， 如果是的话， 就会调用二进制程序加载器。

如果它不是二进制类型的程序， execve(2) 调用会返回一个错误， shell 则会把它当作 shell 命令执行。 “不论当前是哪一种 shell” 都会默认做出此种假设。

随后， sh(1) 会检查开头的两个字符， 如果它们是 `:\n`， 那么就调用 csh(1)。

FreeBSD 有一份加载器列表而不是一个单一的加载器， 并能回退到 `#!` 加载器来运行 shell 解释器或者 shell 脚本。

为了支持 Linux® ABI， FreeBSD 看到了二进制 ELF 程序的魔数。 ELF 加载器会查找一个专用的 标记， 那是在 ELF 镜像中的一个注释部分， 此区域在 SVR4/Solaris™ ELF 二进制中并不存在。

要运行 Linux® 二进制程序， 必须先使用 brandelf(1) 命令 标记 为 `Linux` 类型：

    # brandelf -t Linux file

当 ELF 加载器看到了 `Linux` 标记，便会替换 `proc` 结构中的一个指针。 所有的系统调用都通过此指针来索引。 除此以外， 进程被标记以便对 signal trampoline 代码的陷阱向量做特殊处理， 还有一些其他由 Linux® 内核模块来处理的（细微）修补。

Linux® 系统调用向量包含一个 `sysent[]` 记录的列表， 它的地址位于内核模块之中。

当一个系统调用被 Linux® 二进制程序调用时， 陷阱代码会把系统调用函数指针从 `proc` 解引用至 Linux® 而不是 FreeBSD 的系统调用入口。

Linux® 模式会动态地 reroots 查找。 这与 `union` 文件系统选项是等效的。 首先会试图在 `/compat/linux/`original-path`` 目录查找文件。 如果失败了， 就会在 `/`original-path`` 目录下查找。 这使得需要其它程序的程序得以运行。 例如，Linux® 工具链都可以在 Linux® ABI 的支持下运行。 也就是说 Linux® 二进制程序可以加载并执行 FreeBSD 二进制程序， 如果当前没有相应的 Linux® 二进制程序， 可以在 `/compat/linux` 目录树中放置一个 uname(1) 命令， 使 Linux® 程序不易察觉它们并没有运行在 Linux® 系统上。

事实上， 在 FreeBSD 内核中有一个 Linux® 内核。 所有由内核提供的服务的各种底层功能在 FreeBSD 系统调用表的记录和 Linux® 系统调用表的记录是一样的： 文件系统操作， 虚拟内存操作， 信号发送， 和 System V IPC。 唯一的不同是 FreeBSD 会得到 FreeBSD 的 glue 功能， 而 Linux® 程序会得到 Linux® 的 glue 功能。 FreeBSD 的 glue 功能是静态链接入内核的， 而 Linux® 的 glue 功能可以静态链接， 或者通过内核模块访问。

严格说来其实并没有真正的模拟， 这是一种 ABI 的实现。 有时这被称为 “Linux® 模拟” 是因为在实现的时候还没有其他适合的词用来描述。 要说 FreeBSD 运行 Linux® 二进制程序并不确切， 因为当时代码并还没有被编译进去。

上一页 | 上一级 | 下一页
11.2. 配置 Linux® 二进制兼容模式 | 起始页 | 部分 III. 系统管理

本文档和其它文档可从这里下载： ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题，请先阅读 文档，如不能解决再联系 <questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.