Go
Linux
golang
embedded

組み込みLinuxでGolangのススメ

一年近く、組み込みLinuxでのユーザープロセスをgolangで書くことを試していたのですが、これはいける! という感触を持ちました。
仲間を増やしたいと思うので、ここにその情報を紹介します。

何をしたか

既存の製品をベースにして、新機能の実装をGolangで書いてみました。
既存の部分はCで書いてあります。Golangで書いた新機能部分は別プロセスになっています。
既存部分とのやりとりは場面によって以下を使い分けました。

  • cgoによる関数呼び出し
  • UNIXドメインソケットの通信
  • シグナル

Golangで書いた部分には以下の要素を含みます。

  • UARTやi2cで接続されたセンサーからデータを受け取る
  • インターネット上のWebサービスのAPIを使用する
  • 2Dグラフィックスの描画 (cairoを使用)

最大性能を目指すよりも、十分な性能を手早く形にすることを重視しました。

Golangでよかったところ

(私の感想です。)

  • mmapやioctlのシステムコールを扱うことができる。これで低レベルの部分までcgoに頼らずに直接Golangで記述できた。
  • goroutineを使った非同期処理が非常に簡潔に書ける。
  • GCによるメモリ管理があること。GCによる遅延は問題にはならなかった。
  • PC Linuxで部分的に動作確認したコードを実機(ARM Linux)に持って行くのが楽であった。
  • シミュレータやデータ変換などの周辺ツールもGolangで書くのが楽であった。
  • 意味不明のクラッシュが発生することがなく、デバッガは不要だった。(例えば、sliceの範囲を超えたときにはpanicになってスタックトレースが出力される)

  • cgoでCの関数を呼ぶのも容易。

  • 有用なライブラリが豊富。

  • 既存ライブラリのGolang bindingも多い。(cairoのgo bindingを使用した)

Golangで困ったところ

うまいやり方がわからずに迷ったことはありましたが、そんなに困ったことはありませんでした。
強いてあげれば

  • 実行ファイルのサイズが大きい。

これの対策を別の記事に書きました。
Golangの実行ファイルを複数まとめてトータルのファイルサイズを減らす工夫(busybox方式)

実践的な情報

組み込みLinuxで使う上で必要だったことに関して別に記事を書きました。
Golangから物理メモリを読み書きする
Golangでioctlのシステムコールを使う
GolangでGPIOの割り込み通知を受け取る
GolangのプロセスをFIFO priorityにセットする
Golangでシリアルポート(UART)を使う
GolangでBLE (Bluetooth Low Enagy)を使う
Golangでlogのタイムスタンプをマイクロ秒単位にする方法
Golangで周期的に実行するときのパターン

というわけで

これからも積極的にGolangを使っていきたいと思います。

追記 2018.1.31

参考になりそうなページ
https://github.com/rakyll/go-hardware
http://embd.kidoman.io/