Chapter 24. Linux 執行模式

Table of Contents
24.1. 如何安裝 Linux 執行模式
24.2. 如何在 FreeBSD 下安裝 Mathematica
24.3. 這個 Linux 執行模式是如何運作的 ?

原文由 以及 Rich Murphey 纂寫

24.1. 如何安裝 Linux 執行模式

FreeBSD 下的 Linux 可執行檔相容模式已經可以執行相當多的 a.out 格式或是 ELF 格式的 Linux 可執行檔。在 2.1-STABLE 分支的 Linux 執行模式可以執行 Linux 的 DOOM 和 Mathematica;在 4.3-RELEASE 的版本 的功能更加完整,已經可以執行如 Oracle8, WordPerfect, StarOffice, Acrobat, Quake, Abuse, IDL 和 netrek for Linux 以及許許多多的 Linux 可執行檔。

但 Linux 模擬器並不支援那些專為 Linux 環境撰寫的程式。 其中一例是那些過度使用 Linux 的 /proc 目錄下檔案格式的程式。這是因為 FreeBSD 跟 Linux 在該目錄下 的檔案並非使用相同的格式;或是那些使用專屬於 i386 架構 的呼叫,如起始虛擬 86 的 CPU 模式等。

依照你的 FreeBSD 的版本,載入 Linux 執行模式的方法稍有不同。

24.1.1. 在 3.0-RELEASE 以及之後的版本中安裝 Linux 執行模式

你並不需要在 kernel 設定檔中加入 options LINUX 或是 options COMPAT_LINUX。 Linux 執行模式是藉者 KLD 物件 (``Kernel LoaDable object'') 來達成, (``Loadable Kernel Module``), 你可以在你需要時載入而不需要重新開機。 你需要修改系統起始檔:

  1. /etc/rc.conf,你需要加入:

        linux_enable=YES
  2. 這一行設定會使得在 /etc/rc.i386 中的下面這些程式碼起作用:

        # Start the Linux binary compatibility if requested.
        if [ "X${linux_enable}" = X"YES" ]; then echo -n '
                linux';               linux > /dev/null 2>&1
        fi

如果你要確定 KLD 是否正常載入,你可以使用命令 kldstat

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

如果你不想或是就是無法將載入 Linux KLD 載入,你就需要在 kernel 中靜態鏈結進 Linux 執行模式的程式。 你必須將:

    options  LINUX
這一行加進你的 kernel 組態檔,然後依照 kernel configuration的說明編譯安裝新的 kernel。

24.1.2. 在 2.2.2-RELEASE 及後來版本 2.2 系列中安裝 Linux 執行模式

不再需要設定 options LINUX 或是 options COMPAT LINUX。 Linux 執行模式是利用 LKM 來達成 (``Loadable Kernel Module``), 你可以在你需要時載入而不需要重新開機。 你需要修改系統起始檔:

  1. 在設定檔 /etc/rc.conf,你需要下列的設定:

        linux_enable=YES
  2. 上述設定會使得在開機執行的檔案 /etc/rc.i386

        # Start the Linux binary emulation if requested.
        if [ "X${linux_enable}" = X"YES" ]; then echo -n '
                linux';               linux > /dev/null 2>&1
        fi

如果你要確定 LKM 是否正常工作,你可以使用命令 i modstat

    % modstat
    Type     Id Off Loadaddr Size Info     Rev Module Name
    EXEC      0   4 f09e6000 001c f09ec010   1 linux_mod

也曾有人回報在 2.2-RELEASE 或是之後的某些版本中, 這個命令並不能正常的執行。如果你就是不能將 Linux LKM 載入,你就需要在 kernel 中靜態鏈結進 Linux 模式的程式。 你必須將:

    options  LINUX
這一行加進你的 kernel 組態檔,然後依照 kernel configuration的說明編譯安裝新的 kernel。

24.1.3. 在 2.1-STABLE 安裝 Linux 執行模式

在 2.1-STABLE 中的 GENERIC 組態並沒有加入 Linux 執行模式的設定,你必許自己修該 kernel 組態。 有兩個方法:1. 將該模式靜態地編譯在 kernel 中。 2. 動態的載入 Linux 的 kernel 模組 (loadable kernel module, LKM)。

要起始 Linux 執行模式,將下面這一行設定加到你的 kernel 組態檔 (參閱 /sys/i386/conf/LINT):

    options COMPAT_LINUX

如果你希望執行需要共享記憶體 (shared memory)的軟體如 DOOM,你還需要加入:

    options SYSVSHM

Linux 模模擬器需要 4.3BSD 相容的系統呼叫。 所以你的 kenel 設定檔中要包含:

    options "COMPAT_43"

如果你偏好將執行模式靜態編譯進 kernel 而非使用 LKM, 請加入:

    options  LINUX

接著依照kernel configuration 的說明執行 config 指令等來安裝新的 kernel。

如果你決定使用 LKM,你就需要將該 kernel 模組載入。 請注意 kernel 模組如果跟 kernel 版本不同,可能會造成系統當機。 建議當你安裝新版的 kernel 時,也同時從新安裝 kernel 模組。

    # cd /usr/src/lkm/linux
    # make all install

裝好 kernel 和 LKM 後,以 root 執行 linux 來載入 Linux 執行模式的 kernel 模組:

    # linux
    Linux emulator installed
    Module loaded as ID 0

執行命令 modstat 可知到系統已載入了那些 kernel 模組。

    % modstat
    Type     Id Off Loadaddr Size Info     Rev
    Module Name EXEC      0   3 f0baf000 0018 f0bb4000   1 linux_emulator

你可以讓系統在開機時自動載入 kernel 模組。 在 FreeBSD 2.2.1-RELEASE 以及 2.1-STABLE 版本中, 只須修改 /etc/sysconfig 中:

    linux=YES
這一行,將 NO 改為 NO 即可。FreeBSD 2.1 RELEASE 以及更早的版本中,該檔案並不包含上面這一行, 你則必須修改 /etc/rc.local 並加入下面這一行:

    linux

24.1.4. 安裝 Linux 執行時期程式庫

24.1.4.1. 以 linux_base port 安裝 Linux 執行時期程式庫

許多的 Linux 程式都使用共享程式庫, 你必須安裝這些程式庫你才能執行 Linux 程式。 你可以手動安裝這些程式庫, 你也可以很輕鬆的使用包裝好的 linux_base port 即可;

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

這樣你就有一個可以使用的 linux 相容模式。 傳說 (以及許多通信論壇中的看法 :-) 認為 Linux 執行模式可以很順利的執行使用 ZMAGIC 程式庫 的 Linux 程式;而使用 QMAGIC 程式庫的 (如 Slackware V2.0) 就常常會有問題。也會有些程式會抱怨系統程式庫的次版本不適用, 不過這通常不是問題。

24.1.4.2. 手動安裝程式庫

如果你並沒有安裝 ``ports'' , 也就是在 /usr/port 下的那些檔案, 你可以手動安裝程式庫。 你需要程式所需要用的 Linux 程式庫以及執行時期的連結器。 你也必須建立一個給 linux 用的根目錄 /compat/linux 來安裝 FreeBSD 系統下的 Linux 模擬器的程式庫。 在 FreeBSD 下執行的 Linux 程式將會先到該目錄去找程式庫。 例如一個 Linux 程式需要, FreeBSD 會先試著去找 /compat/linux/lib/libc.so ,如果找不到的話再去找 /lib/libc.so。 程式庫應該安裝在 /compat/linux/lib 目錄下而非 Linux 中的ld.so所 回報的目錄。

FreeBSD-2.2-RELEASE 和以後的版本的工作方式又稍稍不同, 在包括程式庫,以及其它所有檔案都是從假的 Linux 根目錄 /compat/linux找起。

一般來說,在你安裝最初幾個 Linux 程式時你會遇到找不到共用的程式庫的問題。 到後來等你安裝了夠多的程式庫,你就不用再擔心這個問題了。

24.1.4.3. 如何手動安裝程式庫

安裝了 linux_base port 還找不到程式庫怎麼辦? 我怎麼知道要安裝哪個檔案, 去那找這些檔案呢?有兩個方法 (當然都需要 FreeBSD 上的 root 的權限來安裝這些程式庫)

如果你手邊有 Linux 系統,你可以在 Linux 上查看該程式需要的 程式庫,然後將之安裝到 FreeBSD 上去。以 Linux 上的 DOOM 為例, 先將 DOOM 安裝在 Linux 系統上,然後執行 ldd linuxxdoom 來查看該程式需要的程式庫:

    % ldd linuxxdoom
    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 下,還要將 第一欄的 symbolic link 建起來並指向相對的檔案。 也就是說,當你完成之後,在你的 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 所查到主要版本相同的程式庫 (檔名中數字中的第一個),你就不用再安裝將第二欄中的檔案, 你系統上那一個應該可以用。 不果我們通常建議你安裝次版本比較新的程式庫,再你把 symbolic link 指到新版的程式庫之後,你就可以把就版的檔案刪除。 例如你系統上有:

    /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

Note: 請注意 只有 Linux 才需要 symblolic link 機制。FreeBSD 執行時期的程式庫連結器會自動尋找主要版本編號相同的檔案, 完全不需要你費心。

24.1.4.4. 設定 ld.so -- 在 FreeBSD 2.2-RELEASE 以及之後的版本

這一部份只對 FreeBSD 2.2-RELEASE 及以後的版本來說有效。 使用 2.1-STABLE 的請略過此部份。

最後,如果你使用 FreeBSD 2.2-RELEASE, 你必須確定你已安裝好 Linux 執行時期程式庫連結器以及其組態檔。 你需要將這些檔案從 Linux 系統安裝到 FreeBSD 的對應處 (/compat/linux 目錄下)

    /compat/linux/lib/ld.so
    /compat/linux/etc/ld.so.config

如果你手邊沒有 Linux 系統,你應該要到 ftp 站去找到這些檔案。 下面有你可以找到這些檔案的資訊。從這裡開始, 我們會假設你知道如何去找到這些檔案。

抓回下面這些檔案 (請從同一個 ftp 站抓下來以免遇到版本不一致的問題)。 並將之安裝在 /compat/linux (也就是說, /foo/bar 就安裝在 /compat/linux/foo/bar):

    /sbin/ldconfig
    /usr/bin/ldd
    /lib/libc.so.x.y.z
    /lib/ld.so

ldconfigldd 並不需要安裝在 /compat/linux下; 你可以將他們安裝在系統的其他地方。 不過要確定不要讓他們跟 FreeBSD 對應的檔案混在一起。通常我們建議將這兩個檔案安裝在 /usr/local/bin 下的 ldconfig-linux 以及 ldd-linux

建立一個檔案 /compat/linux/etc/ld.so.conf,包含了 Linux 執行時期程式庫連結器搜尋程式庫的目錄。 這個檔案是個純文字檔,每一行包含一個目錄。 /lib/usr/lib 是標準的,通常你需要再加入:

    /usr/X11/lib
    /usr/local/lib

當 Linux 程式開啟一個檔案如 /lib/libc.so ,Linux 支援 ABI 將該檔名對應到 /compat/linux/lib/libc.so。 所有的 Linux 程式應該要裝在 /compat/linux (也就是指 /compat/linux/lib/libc.so, /compat/linux/usr/X11/lib/libX11.so, 等等。) 這樣 Linux ABI 才能正確的找到。

使用 FreeBSD 2.2-RELEASE 需要執行 Linux 程式 ldconfig

    # cd /compat/linux/lib
    # /compat/linux/sbin/ldconfig

ldconfig 是靜態連結的程式, 並不需要任何動態程式庫。它會產生 /compat/linux/etc/ld.so.cache 這個檔案,包含了所有共享程式庫的檔名。 當你安裝了新的共享程式庫之後,你需要重新執行這個程式。

在 2.1-STABLE 請勿安裝 /compat/linux/etc/ld.so.cache 或是執行 ldconfig;在 2.1-STALE 中系統呼叫的寫法稍有不同, ldconfig 並不需要也不會被使用到。

你現在的設定應該可以執行只需要 libc 共享程式庫的程式。 你可以試著執行 Linux 的 ldd 在它自己身上。 假設將它安裝為 ldd-linux 其輸出約略如下:

    # ldd-linux `which ldd-linux`
    libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29

如果是這樣的的話,你就可以開始安裝新的 Linux 程式了。 當你安裝新的 Linux 程式,你應該檢查它是否需要新的程式庫, 如果是的話, 你就把它裝在 /compat/linux 下。 然後執行 Linux 的 ldd 在新的程式, 看看輸出為何。ldd (請看 ldd(1) 的 man page) 將以 [主名稱 => 全名稱] 的格式印出程式需要的程式庫名稱。 majorname (jumpversion) => fullname.

如果它印出 not found (找不到) 而不是 fullname, 那意味者你需要再安裝新的程式庫。 所需要的程式庫在主名稱中會顯示出來, 通常以 libXXXX.so.N 的格式顯示。你將需要去 Linux ftp 站找到檔名為 libXXXX.so.N.mm, 然後將之安裝在你的系統。 XXXX (名稱) and N (主要版本編號) 應該要一樣; 次版本名稱 mm 就不是那麼重要, 當然我們通常建議你找比較新的版本。

24.1.5. 安裝 Linux ELF 程式

ELF 格式的程式需要額外的''標示''。 如果你要執行一個沒有標示的 ELF 程式,你將會得到如下的訊息:

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

為了讓 FreeBSD 系統分辨是否是一個 ELF 的程式,請用工具SD ELF brandelf(1)

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

GNU 的工用程式在未來會自動處理這個問題, 你以後遇到這個問題的機會會越來越少。

24.1.6. 設定 DNS 解析器

如果 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 和 Linux 在這 個檔案的設定語法不同,而抱怨語法不合。 如果你在 /etc/resolv.conf 中沒有設定 DNS 的話,就移去 bind

最後, 如果你使用的是 2.1-STABLE,你須要設定環境變數 RESOLV_HOST_CONF , 這樣 Linux 模擬器才能知道去那裡找到 DNS。 如果你使用 FreeBSD 2.2-RELEASE 或是後來的板本, 你可以不用做此設定。 如果你使用 /bin/csh 請輸入:

    % setenv RESOLV_HOST_CONF /compat/linux/etc/host.conf

如果你使用 /bin/sh ,請輸入:

    % RESOLV_HOST_CONF=/compat/linux/etc/host.conf; export RESOLV_HOST_CONF

24.1.7. 找到所需要的程式庫

Note: 注意,下面的資訊在本文寫作時是正確的, 但一些如 ftp 站的名稱或是檔案放置的目錄或是發行版本名稱等, 在你閱讀本文時可能已經改變了。

有許多團體發行他們自己的 Linux 版本。每個發行版本都有名字如 ``Slackware'' 或是 ``Yggdrasil''。 你可以在各大 FTP 站找到他們。 有些檔案沒有被包裝,你可以一個個將他們下載。 但大部份都以各自的方式包裝, 通常是將整個檔案同目錄 TAR 起來,再以 gzip 壓縮。 這些發行版本主要的站在:

  1. sunsite.unc.edu:/pub/Linux/distributions

  2. tsx-11.mit.edu:/pub/linux/distributions

一些在歐洲的 mirror 站:

  1. ftp.luth.se:/pub/linux/distributions

  2. ftp.demon.co.uk:/pub/unix/linux

  3. src.doc.ic.ac.uk:/packages/linux/distributions

為簡單起見,我們在此只談 Slackware 這個版本。 這個發行版本包函了許多子目錄, 其下有單獨的檔案包裝。這些些檔案包裝通常是讓自動安裝程式讀的, 不過你也可以 `` 手動 '' 取得其中的檔案。 首先,你先要看看各目錄的內容。你可以察看各目錄下的 檔案 contents, 其內容是敘述各個檔案包裝內容的文件檔。 最快的方法是,把位於各子目錄中的敘述文件檔都取回, 然後用 grep 程式找到你要的檔案。 這裡有一個或許是你須要的檔案的例子:

LibraryPackage
ld.soldso
ldconfigldso
lddldso
libc.so.4shlibs
libX11.so.6.0xf_lib
libXt.so.6.0xf_lib
libX11.so.3oldlibs
libXt.so.3oldlibs

在個例子中,你需共需要檔案包裝 ldso, shlibs, xf_lib 和 oldlibs。在這些資料中,請找到一行寫有 PACKAGE LOCATION,它會告訴你在那片 ``磁片'' 你可以找到該程式包裝,在我們舉的例子中, 它告訴我們你可以在哪個目錄下找到它。 在這個例子中,我們找到:

PackageLocation
ldsodiska2
shlibsdiska2
oldlibsdiskx6
xf_libdiskx9

在 Locations 這一欄中的 ``diskXX'' 也就是相對於 slakware/XX 這個目錄。 另外有些可以在 contrib 這個子目錄中找到。 在這個例子中,我們將抓回下列檔案 (相對於 Slackwzre 這個發行版本的根目錄來說):

  • slakware/a2/ldso.tgz

  • slakware/a2/shlibs.tgz

  • slakware/x6/oldlibs.tgz

  • slakware/x9/xf_lib.tgz

將這些檔案在你的 /compat/linux 這個目錄下解開, (當然你可以不用安裝某些你並不需要的檔案) 這樣就大公告成了。

請參考: ftp://ftp.FreeBSD.org:pub/FreeBSD/2.0.5-RELEASE/xperimnt/linux-emu/README and /usr/src/sys/i386/ibcs2/README.iBCS2