10.3. 進階主題

本節描述 Linux® 二進位檔如何運作,以 Terry Lambert 寫給FreeBSD chat 郵遞論壇的電子郵件為基礎(Message ID: <199906020108.SAA07001@usr09.primenet.com>)。

FreeBSD has an abstraction called an execution class loader. This is a wedge into the execve(2) system call.

歷史上, UNIX® 載入器檢查魔術數字(通常是檔案的頭四或八個位元組)來看它是否是系統已知的二進位檔,如果是,就調用二進位檔載入器。

如果不是系統的二進位檔類型, execve(2) 呼叫會回報失敗,shell會嘗試當作 shell 指令來執行。 The assumption was a default of whatever the current shell is.

後來, sh(1) 做了hack來檢查頭兩字元,如果他們是 :\n,就改調用 csh(1) shell 。

FreeBSD 有一系列的載入器取代單一載入器,其中有with a fallback to the #! 載入器來執行 shell 解譯器或是 shell 腳本。

對於 Linux® ABI 支援, FreeBSD 將魔術數字看待為 ELF 二進位檔。 ELF載入器尋找專門的 brand,這是 ELF 影像的註解部份,並未存在於 SVR4/Solaris™ ELF 二進位檔。

For Linux® binaries to function, they must be branded as type Linux using brandelf(1):

# brandelf -t Linux file

When the ELF loader sees the Linux brand, the loader replaces a pointer in the proc structure. All system calls are indexed through this pointer. In addition, the process is flagged for special handling of the trap vector for the signal trampoline code, and several other (minor) fix-ups that are handled by the Linux® kernel module.

The Linux® system call vector contains, among other things, a list of sysent[] entries whose addresses reside in the kernel module.

When a system call is called by the Linux® binary, the trap code dereferences the system call function pointer off the proc structure, and gets the Linux®, not the FreeBSD, system call entry points.

Linux® mode dynamically reroots lookups. This is, in effect, equivalent to the union option to file system mounts. First, an attempt is made to lookup the file in /compat/linux/original-path. If that fails, the lookup is done in /original-path. This makes sure that binaries that require other binaries can run. For example, the Linux® toolchain can all run under Linux® ABI support. It also means that the Linux® binaries can load and execute FreeBSD binaries, if there are no corresponding Linux® binaries present, and that a uname(1) command can be placed in the /compat/linux directory tree to ensure that the Linux® binaries can not tell they are not running on Linux®.

In effect, there is a Linux® kernel in the FreeBSD kernel. The various underlying functions that implement all of the services provided by the kernel are identical to both the FreeBSD system call table entries, and the Linux® system call table entries: file system operations, virtual memory operations, signal delivery, and System V IPC. The only difference is that FreeBSD binaries get the FreeBSD glue functions, and Linux® binaries get the Linux® glue functions. The FreeBSD glue functions are statically linked into the kernel, and the Linux® glue functions can be statically linked, or they can be accessed via a kernel module.

Technically, this is not really emulation, it is an ABI implementation. It is sometimes called Linux® emulation because the implementation was done at a time when there was no other word to describe what was going on. Saying that FreeBSD ran Linux® binaries was not true, since the code was not compiled in.

本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。

關於本文件的問題,請洽詢 <doc@FreeBSD.org>。