FreeBSDでLinuxバイナリ互換機能を使ってみる

概要

FreeBSDハンドブック 10.2. Linux® バイナリ互換機能の設定 を参照してLinuxバイナリ互換機能を有効化した上で、適当なLinuxバイナリを用意して動かしてみた。

目次

  • Linuxバイナリ互換機能の準備
  • Linuxバイナリの用意
  • Linuxバイナリを実行する
  • まとめ

Linuxバイナリ互換機能の準備

FreeBSDにはLinux用の実行バイナリに手を加えずにそのまま実行するLinuxバイナリ互換機能(Linuxulatorと呼ばれる)がある。ハンドブックを参照して、カーネルモジュールを読み込んでLinuxバイナリ実行用のライブラリをインストールする。

sudo kldload linux
sudo kldload linux64
sudo pkg install emulators/linux_base-c7

/etc/rc.conf に以下を記載しておけば再起動後もLinuxバイナリ互換機能が有効化される。

linux_enable="YES"

/etc/fstab に以下を記載し、マウントする。今回動かすプログラムでは利用しなくても大丈夫だが、/proc, /sys, /dev/shmを使うようなプログラムでも動作させることができるらしい。

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
sudo mount /compat/linux/proc
sudo mount /compat/linux/sys
sudo mount /compat/linux/dev/shm

Linuxバイナリの用意

GoでLinux用のバイナリを用意する。環境変数の設定だけで簡単にクロスコンパイルできるので便利。

sudo pkg install go

main.go を用意する。

package main

import "fmt"

func main() {
	fmt.Println("Hello, world!")
}

今回はFreeBSD/Linux用に32/64ビットのバイナリをそれぞれクロスコンパイルし、合計4種類のバイナリを作った。

GOOS=freebsd GOARCH=amd64 go build -o fbsd64  main.go
GOOS=freebsd GOARCH=386   go build -o fbsd32  main.go
GOOS=linux   GOARCH=amd64 go build -o linux64 main.go
GOOS=linux   GOARCH=386   go build -o linux32 main.go

用意した4つのバイナリ情報をfileコマンドで確認してみる。Linux用もFreeBSD用もどちらもELF。FreeBSD用は version 1 (FreeBSD)、Linux用は version 1 (SYSV) となっている。

$ file fbsd64
fbsd64: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), statically linked, Go BuildID=xykiihtRL-scj4GSy8TO/FjVgZBRW9niD_shI5R1O/FkbAyAK_QYuQ3TEUFh_l/9LvbDPm51xbB_lBWHVKZ, not stripped

$ file fbsd32
fbsd32: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), statically linked, Go BuildID=fOhR-AY5kFev4BcpCYeg/fcgG3V0uH6RYUjBnIIWb/mAmAODzKjUcnHQZtCy1T/_wK_cmGC3cE9lzrssCvn, not stripped

$ file linux64
linux64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=3YU53_PCF9Kf6dJNp_J3/ZVf_vs-V5DxzzYXii6Ja/BkGJrDeLhJvAZP7roVvj/rUTq6c3E2mZkul9tVqpL, not stripped

$ file linux32
linux32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, Go BuildID=iyjpm6fSu-HqkhaKP-iH/uvELtFgAVuTgNbCYJqqu/KXC8dfX2tvgxegYR5ruF/shi8YgOLtzddgmysbwO0, not stripped

Linuxバイナリを実行する

FreeBSD用のバイナリは64ビット版、32ビット版ともに実行できるが、Linux用のバイナリはそのままでは実行に失敗する。

$ ./fbsd64
Hello, world!

$ ./fbsd32
Hello, world!

$ ./linux64
ELF binary type "0" not known.
bash: ./linux64: cannot execute binary file: Exec format error

$ ./linux32
ELF binary type "0" not known.
bash: ./linux32: cannot execute binary file: Exec format error

Linux用にクロスコンパイルした実行バイナリを、brandelfコマンドでバイナリタイプにLinuxを指定すると動くようになる。

brandelf -t Linux linux64
brandelf -t Linux linux32
$ ./linux64 
Hello, world!

$ ./linux32 
Hello, world!

fileコマンドでLinuxバイナリを見てみると、ELFバイナリであることに変わりはない。先程は version 1 (SYSV) となっていたが、brandelf実行後は version 1 (GNU/Linux) となっている。

$ file linux64
linux64: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, Go BuildID=3YU53_PCF9Kf6dJNp_J3/ZVf_vs-V5DxzzYXii6Ja/BkGJrDeLhJvAZP7roVvj/rUTq6c3E2mZkul9tVqpL, not stripped

$ file linux32
linux32: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, Go BuildID=iyjpm6fSu-HqkhaKP-iH/uvELtFgAVuTgNbCYJqqu/KXC8dfX2tvgxegYR5ruF/shi8YgOLtzddgmysbwO0, not stripped

まとめ

FreeBSDのLinuxバイナリ互換機能を利用して、Linux用のバイナリを実行した。用意したLinux用バイナリはそのままでは実行できず、brandelfコマンドでバイナリタイプをLinux指定することで実行できるようになった。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA