はじめに
「FreeBSD使いたいけど、Linuxアプリが動かないと困る...」
安心して。FreeBSDはLinuxバイナリをそのまま動かせる。
エミュレーションじゃなくて、カーネルレベルでLinuxシステムコールをサポートしてる。
Linuxulatorとは
┌─────────────────────────────────────────────────────────────┐
│ Linuxulator Architecture │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Linux バイナリ │ │
│ │ (ELF, glibc, etc.) │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ syscall │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ linux.ko (Linuxシステムコール変換) │ │
│ │ │ │
│ │ sys_linux_open() → sys_open() │ │
│ │ sys_linux_stat() → sys_stat() │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ FreeBSD カーネル │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
カーネルモジュールがLinuxのシステムコールをFreeBSDのシステムコールに変換する。
有効化
カーネルモジュールのロード
kldload linux64
永続化
# /etc/rc.conf
linux_enable="YES"
# または /boot/loader.conf
linux64_load="YES"
確認
kldstat | grep linux
# 4 1 0xffffffff82400000 41000 linux64.ko
Linuxユーザーランドのインストール
CentOS 7ベース(推奨)
pkg install linux_base-c7
これで/compat/linux/にLinuxのベースシステムがインストールされる。
ls /compat/linux/
# bin dev etc lib lib64 opt proc root run sbin sys tmp usr var
必要に応じて追加パッケージ
pkg install linux-c7-gtk3
pkg install linux-c7-alsa-lib
pkg install linux-c7-dbus-libs
pkg install linux-c7-nss
procfsとlinprocfsのマウント
Linuxアプリが/procを使う場合に必要。
# /etc/fstab
linprocfs /compat/linux/proc linprocfs rw 0 0
linsysfs /compat/linux/sys linsysfs rw 0 0
tmpfs /compat/linux/dev/shm tmpfs rw,mode=1777 0 0
# マウント
mount /compat/linux/proc
mount /compat/linux/sys
mount /compat/linux/dev/shm
動作確認
Linuxのlsを実行
/compat/linux/bin/ls --version
# ls (GNU coreutils) 8.22
brandelfで確認
brandelf /compat/linux/bin/ls
# File '/compat/linux/bin/ls' is of brand 'Linux'.
実用例1: Linuxバイナリを直接実行
# Linuxのbashを実行
/compat/linux/bin/bash
# Linuxのpythonを実行(インストール済みの場合)
/compat/linux/usr/bin/python3
実用例2: Steamを動かす
# 依存パッケージ
pkg install linux-steam-utils
# Steamを起動
steam
トラブルシューティング
# 32bitライブラリが必要な場合
pkg install linux_base-c7
pkg install linux-c7-nss
pkg install linux-c7-alsa-plugins
# GPUドライバ
pkg install linux-nvidia-libs # NVIDIA
pkg install linux-c7-dri # Mesa
実用例3: LinuxのDockerを動かす(実験的)
# linux64 with Docker support (FreeBSD 14+)
pkg install linux-docker
※完全な互換性はまだない。本格的にDockerを使うならjailやbhyveを検討。
実用例4: Spotifyを動かす
# 必要なライブラリ
pkg install linux-c7-gtk3
pkg install linux-c7-alsa-plugins
pkg install linux-c7-nss
pkg install linux-c7-libcurl
# Spotifyをダウンロード(debパッケージを展開)
fetch https://repository-origin.spotify.com/pool/non-free/s/spotify-client/spotify-client_1.2.8.923_amd64.deb
ar x spotify-client_*.deb
tar xf data.tar.xz -C /compat/linux/opt/
# 実行
/compat/linux/opt/spotify/spotify
実用例5: VS Code(code-oss)
# Electronアプリには追加のライブラリが必要
pkg install linux-c7-gtk3 linux-c7-libxkbcommon linux-c7-nss
# VS Codeをダウンロード・展開
fetch https://update.code.visualstudio.com/latest/linux-x64/stable -o code.tar.gz
tar xf code.tar.gz -C /compat/linux/opt/
# 実行
/compat/linux/opt/VSCode-linux-x64/code
環境変数の設定
Linuxアプリを快適に使うための設定。
# ~/.bashrc または ~/.profile
export LD_LIBRARY_PATH=/compat/linux/usr/lib64:/compat/linux/lib64
export LIBGL_DRIVERS_PATH=/compat/linux/usr/lib64/dri
デバッグ
システムコールのトレース
truss /compat/linux/bin/ls
エラーの確認
# linuxのライブラリが見つからない場合
ldd /compat/linux/opt/someapp/bin/app
# libsomething.so.1 => not found
# 足りないライブラリを探す
pkg search linux-c7 | grep something
LD_DEBUGで詳細表示
LD_DEBUG=libs /compat/linux/opt/someapp/bin/app
パフォーマンス
LinuxulatorはエミュレーションではなくABI互換レイヤーなので、オーバーヘッドはほぼゼロ。
# ネイティブ vs Linux版
time /bin/ls -laR /usr > /dev/null
# real 0.123s
time /compat/linux/bin/ls -laR /usr > /dev/null
# real 0.125s # ほぼ同じ
制限事項
動かないもの
- Linuxカーネルモジュール(当然)
-
/devの特殊なデバイス(一部) -
ptraceを使う高度なデバッガ(一部制限) - 最新のLinuxカーネル機能を使うアプリ
要注意
- セキュリティパッチ: CentOS 7のライブラリは古い
- glibcバージョン: 新しいLinuxバイナリは動かない可能性
- 32bit:
linux_base-c7はx86_64用
Ubuntuベースを使いたい場合
CentOS 7じゃなくてUbuntuを使いたい場合、debootstrapを使う。
pkg install debootstrap
# Ubuntu chrootを作成
debootstrap --arch=amd64 jammy /compat/ubuntu http://archive.ubuntu.com/ubuntu
# /etc/fstabに追加(procfs等)
ただし公式サポートはCentOS 7なので、自己責任で。
jail内でLinuxを動かす
より隔離された環境でLinuxバイナリを動かしたい場合。
# jail.conf
exec.start = "/compat/linux/bin/sh /compat/linux/etc/rc";
allow.mount.linprocfs;
allow.mount.linsysfs;
まとめ
FreeBSDのLinuxバイナリ互換機能:
- linux64.koでシステムコールを変換
- linux_base-c7でCentOS 7ユーザーランド
- Steamなどのゲームも動く
- パフォーマンスオーバーヘッドはほぼゼロ
「FreeBSDだとあのアプリが使えない」という言い訳はもう通用しない。
この記事が役に立ったら、いいね・ストックしてもらえると嬉しいです!