3.0-RELEASE以降であればカーネルのコンフィギュレーションファイルに options LINUX や options COMPAT_LINUX といった行を加える必要はありません.
Linux バイナリ互換機能は今は KLD オブジェクト ("Kernel LoaDable object") として実現されており, リブートしなくても "on-the-fly" で組み込むことができるのですが, /etc/rc.confに次の行を加える必要があります.
linux_enable="YES"この設定により, /etc/rc.i386 では次のような操作が行なわれます.
# Start the Linux binary compatibility if requested.
#
case ${linux_enable} in
[Yy][Ee][Ss])
echo -n ' linux'; linux > /dev/null 2>&1
;;
esac
望みの KLD モジュールがロードされているか確認したい時には kldstat を利用します.
% kldstat
Id Refs Address Size Name
1 2 0xc0100000 16bdb8 kernel
7 1 0xc24db000 d000 linux.ko何らかの理由で Linux KLD をロードしたくない, あるいはロードできないような場合には, options LINUX をカーネルの設定ファイルに指定して, Linux バイナリ互換機能をカーネルにスタティックリンクしてください. そして, FreeBSD カーネルのコンフィギュレーション の記述にしたがって新しいカーネルをインストールしてください.
これは, linux_base の port を用いるか, もしくは 手動でインストールします.
ランタイムライブラリをインストールするには最も簡単な方法です. ports コレクションから他の port をインストールするのと全く同じようにできます.
# cd /usr/ports/emulators/linux_base
# make install distcleanこれで Linux バイナリ互換機能が使えるはずです. いつかのプログラムはシステムライブラリのマイナーバージョンが違うと文句を言うかもしれませんが一般的には大した問題ではありません.
"ports"コレクションをインストールしていない場合, 代わりに手動でライブラリをインストールすることができます. プログラムが必要とする Linux のシェアードライブラリとランタイムリンカが必要です. また Linux ライブラリ用の "shadow root" ディレクトリ, /compat/linux, を作成する必要があります. FreeBSD で動作する Linux プログラムが使用するシェアードライブラリは, まずこのファイルツリーから検索されます. 例えば, Linux のプログラムが /lib/libc.so をロードしようとした場合には, FreeBSD はまず /compat/linux/lib/libc.so を開こうとします. これが存在しなかった場合には, 次に /lib/libc.so を試します. シェアードライブラリは, Linux の ld.so が報告するパスではなく, /compat/linux/lib 以下にインストールする 必要があります.
Linux のプログラムが必要とする シェアードライブラリを探す必要があるのは, FreeBSD のシステムに Linux のプログラムをインストールする最初の数回だけでしょう. それが過ぎれば, 十分な Linux のシェアードライブラリがシステムにインストールされ, 新しくインストールした Linux のバイナリも余計な作業をせずに動作させることができるようになります.
linux_base port をインストールした後に, アプリケーションが必要なライブラリが存在しないというエラーを出したらどうしたらよいでしょうか? Linux のバイナリがどのシェアードライブラリを必要とし, そしてどこで入手できるか, どのように探したらよいでしょうか? 基本的には, 以下の 2 種類の方法があります (以下の手順に従う場合には, 必要なインストール作業をおこなう FreeBSD システム上で root として作業をおこなう必要があります).
Linux システムにアクセス可能ならば, そのアプリケーションがどういうシェアードライブラリを必要としているのか調べ, 単に FreeBSD にそのライブラリをコピーするだけです. 次の例を見てみましょう.
FTP を使って Doom の Linux バイナリを取ってきて, アクセスできる Linux システムに置いたとしましょう. 次のように ldd linuxdoom とするだけでどのシェアードライブラリが必要かチェックできます.
% 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 の下に置き, 最初のカラムに示されるファイル名にシンボリックリンクを張ります. すなわち, 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.29Note: 最初のカラムに表示されているファイルとメジャーバージョンが同じ 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このように最後の番号が1つか2つ古いだけならば, 普通は /lib/libc.so.4.6.29 をコピーする必要はありません. わずかに古いライブラリでもプログラムは動作するはずだからです. もちろん, 以下のように新しいライブラリと置き換えても構いません.
/compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -> libc.so.4.6.29
Note: シンボリックリンクのメカニズムは Linux バイナリにのみ必要なことに注意してください. FreeBSD のランタイムリンカはメジャーリビジョン番号の一致したライブラリを検索するので, ユーザが気にする必要はありません.
ELF のバイナリを使うためには, "マークをつける (branding)" 作業が必要になります. マークのない ELF バイナリを実行しようとすると以下のようなエラーメッセージを受けとってしまうことでしょう.
% ./my-linux-elf-binary
ELF binary type not known
Abortカーネルが FreeBSD の ELF バイナリと Linux のバイナリとを 見分けられるようにするためには, brandelf(1) ユーティリティを以下のようにして使ってください.
% brandelf -t Linux my-linux-elf-binary
今ではGNU のツールたちが ELF バイナリに自動的に適切なマークを付加するようになったので, 今後はこの作業もだんだんと必要なくなってゆくでしょう.
DNS がうまく動作しなかったり, 以下のようなエラーメッセージが表示され る場合は, /compat/linux/etc/host.conf ファイルを設定する必要があります.
resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keywordファイルの内容を以下のように設定してください.
order hosts, bind
multi onここで, order は /etc/hosts を最初に検索し, 次にDNSを検索するように指定します. /compat/linux/etc/host.conf がインストールされていない場合, Linux アプリケーションは FreeBSD の /etc/host.conf を使用しようとして, 文法の違いによる警告を出力します. /etc/resolv.conf を利用してネームサーバの設定をしていない場合には, bind を削除してください.