post Image
Go 1.8のMIPS32バイナリをルータ上で動かしてみた(成功編)

Go 1.8から32bit MIPS Linux環境がサポートされました(参考:https://tip.golang.org/doc/go1.8#ports )。32bit MIPSは組み込み系開発ボードなどに多く採用されているCPUで、身近なところでは家庭用ブロードバンドルータの半分以上1でMIPS32が採用されています。つまりブロードバンドルータ上でGoプログラムが動くというわけです。これはアツいですね!

本稿ではまず簡単なGoプログラムをMIPSベースのブロードバンドルータ上で動かします。次に、GoのMIPS32サポートの現状と今後について紹介します。

動かしてみた

では、さっそくGoでMIPS32バイナリを生成してみましょう。まずはGo 1.8RC1をインストールします。

$ go get golang.org/x/build/version/go1.8rc1
$ go1.8rc1 download

次に、下記のGoプログラムを用意します。

hello.go
package main

import "fmt"

func main() {
    fmt.Printf("Hello, world!\n")
}

次のようにコンパイルすれば32-bit MIPS用のhelloバイナリが得られます。

$ GOOS=linux GOARCH=mips go1.8rc1 build hello.go
$ file hello
hello: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped

さて、実際に動かしてみましょう。筆者はBuffalo社の有線ブロードバンドルータBHR-4GRV上にOpenWrtというLinuxディストリビューションをインストールしています。

このブロードバンドルータにscpでバイナリを送り込むと、バイナリが動作しました。

$ scp hello openwrt01:/tmp
$ ssh openwrt01


BusyBox v1.23.2 (2017-01-19 17:27:24 UTC) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Chaos Calmer, unknown)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
# /tmp/hello
Hello, world!

こう書くと簡単に動くように見えますが、実はこのバイナリは多くの環境で動作しません。上記の環境ではこのバイナリを動かすため自前のカーネルに入れ替えています。

現時点のGoのMIPS32サポート状況

Go 1.8のリリースノートには、次のような記述があります。

Go now supports 32-bit MIPS on Linux for both big-endian (linux/mips) and little-endian machines (linux/mipsle) that implement the MIPS32r1 instruction set with FPU or kernel FPU emulation. Note that many common MIPS-based routers lack an FPU and have firmware that doesn’t enable kernel FPU emulation; Go won’t run on such machines.

Go 1.8の32-bit MIPSサポートはFPU(浮動小数点演算ユニット)またはカーネルによるFPUエミュレーションが必須だと書いてあります。これを満たす32-bit MIPS環境はごく少数であるため、かなり厳しい制約だと言えるでしょう。

実際、私の持っているブロードバンドルータにはFPUはありませんし、OpenWrtでもカーネルFPUエミュレーションはデフォルトで無効になっています。FPUエミュエーション有効にしてカーネルビルドしなおしたのが上の環境というわけです。

カーネルFPUエミュレーションとsoft-float

ところで、FPUが無い環境というのは組み込み系では珍しくありません。そうした環境でもC言語でfloatdoubleなどの型が使えるのはなぜでしょうか。

実は、整数演算命令のみで浮動小数点数演算を実現する機構が大半のCコンパイラで提供されています。これはsoftware floating pointとかsoft-floatなどと呼ばれます。この仕組みにより、FPUの無い環境でも浮動小数点数演算が実現できているわけです。逆に、Go 1.8でFPU必須という制約がついているのはsoft-floatが未実装であるという意味でもあります。

一方で、今回の実験で使ったようにカーネル側でFPU命令のエミュレーションを行うアプローチも考えられます。これはARM LinuxとMIPS Linuxで提供されている機構のようです(私が知らないだけで、他の環境でも珍しくないのかもしれません)。これを使えばコンパイラ側の実装コストは減りますが、FPU命令が発効されるたびにカーネル割り込みが走るため速度面ではかなり不利です。カーネルFPUエミュレーションとsoft-floatの好きな方が選べるのであれば、当然後者を選ぶべきです。

もちろんGoの中の人も同じ認識のようで、既にMIPS32のsoft-floatサポートについて議論されています(参考:「runtime: mips32 soft float point support · Issue #18162 · golang/go」)。ただ、Go 1.8のタイミングでは時間切れだったということのようです。Go 1.9以降に期待したいですね。

まとめ

  • Go 1.8でMIPS32バイナリが出力できるようになった
    • ただし、このバイナリが動く環境は少ないと思われる。大抵の環境ではカーネルリコンパイルが必要。
  • Go 1.9以降MIPS32のsoft-floatサポートが入るはず、そのタイミングが本命

  1. 組み込み系素人の感覚値です 


『 Go 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。