Yoctoベースの組み込みLinuxがビルドエラーになったときに試したこと


この記事は Linuxアドベントカレンダー2021 の24日目の記事なります。
前日の23日目は @leosuke さんによる
【元Linux向けアプリケーション開発者がおすすめする本「C言語によるスーパーLinuxプログラミング」の紹介】でした。
私は知らなかった本で有用な知識が得られると感じました。是非、読んでみたいと思いました。

自己紹介

組み込みソフトウェアエンジニアでベアメタルな開発がほとんどです。
Linuxを適用した組み込み製品開発の経験はありません。
今回、学習目的で組み込みLinuxの環境構築にチャレンジしたのでそのプロセスを共有したいと考えました。
つっこみどころが多々あると思いますが暖かい気持ちで読んでいただけるとありがたいです。

やったこと

ラズパイ4 ModelB 8GでYoctoベースの組み込みLinux「Wind River Linux(バージョン: 10.19.45.19)」を動かせました。
基本、APSさんの記事とおりに実施しました。
実施したことは次の2つです。

  1. カーネルモジュールのビルド
  2. Wind River Linuxのビルド

実施しましたがビルドエラー⇔調査・対策の試行錯誤がありました。
この調査・対策の試行錯誤を共有すれば何か役に立つかもしれないと考えました。

次は当時のツイートです。

APSさんの記事は次を参考にしました。
カーネルモジュールのビルドは次を参考にしました。

Wind River Linuxのビルドは次を参考にしました。

環境

ホストPC環境

Windows PCにVirtualBoxをインストールし、ゲストOSをUbuntu 18.04.5 Desktop 64bitにしました。
APSさんのWebページだとCentOS 7を使っていましたがサポート終了のニュースが流れていました。
Ubuntu 18.04はWind River Linux 10.19.45.19に対応しているので決めました。

ホストPCの推奨条件:

LinuxホストPCの推奨条件:

disk空き容量は500Gバイトくらいあると安心かと思います。

ホストPCのスペック

ホストPCのスペックは次のとおりです。

  • OS: Windows 10 Pro バージョン20H2
  • プロセッサ: Intel(R) Core(TM) i7-8700 CPU @3.20GHz
  • メモリ: 8G
  • 64bit
  • SSD 1T

このホストPCにVirtualBox 6.1をインストールしました。

VirtualBoxの設定

VirtualBoxの設定は次のとおりです。

設定全体像:

メモリ:
メモリは設定可能上限値の5G程度にしました。

プロセッサ:
環境構築当初は6コアに設定していましたが後述する理由で最終的に1コアに設定変更しました。

ディスプレイ:
こちらはデフォルトのままです。

ネットワーク:
ブリッジアダプターに変更しました。

ラズパイ環境

ラズパイ4の必要条件は次になります。

次のリンクの【Raspberry Pi 4 Model B で組み込みLinuxディストリビューション開発】のとおりです。

  • Raspberry Pi 4 Model B+ メモリ 4GB
  • microSDカード 16GB ⇛ 32Gを使いました。
  • microSDカードリーダ
  • USB-C給電ケーブル
  • 有線LANケーブル
  • USBマウス
  • USBキーボード
  • microHDMI to HDMI変換ケーブル
  • HDMIケーブル
  • HDMI対応ディスプレイ

カーネルモジュールのビルド

カーネルモジュールのビルドは次のリンクを参照しそのまま実行していきました。

リンクの【Wind River LinuxでLinuxディストリビューションとSDKをビルドする】で次のコマンドを実行します。

bitbake wrlinux-image-glibc-std -c populate_sdk

【エラー】
ビルドがエラーで失敗していました。
dmesgでエラー内容を確認すると【Out of memory】が発生していました。

[ 1095.180723] [  12067]  1000 12067    25572      134    61440       38             0 tar
[ 1095.180725] [  12068]  1000 12068  2055002  1155100 10846208   174013             0 xz
[ 1095.180726] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=xz,pid=12068,uid=1000
[ 1095.180833] Out of memory: Killed process 12068 (xz) total-vm:8220008kB, anon-rss:4620400kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:10592kB oom_score_adj:0
[ 1095.347151] oom_reaper: reaped process 12068 (xz), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
[ 1671.482412] sched: RT throttling activated

【対策】
UbuntuのGUIをオフにしました。
次のコマンドを実行しUbuntuのGUIをオフにしてCUIでビルドするようにします。
メモリを節約してビルドすることが狙いでした。

sudo systemctl set-default multi-user.target 

参考情報:

【対策効果確認】
この対策でbitbakeコマンドが正常に終了することができました。

次はAPSさんのリンクの【カーネルモジュールのビルド準備をする】の次のコマンドでエラーが発生しました。

make modules_prepare

【エラー】

koji@koji-VirtualBox:/opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/usr/src/kernel$ make modules_prepare
  HOSTCC  scripts/extract-cert
scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: そのようなファイルやディレクトリはありません
 #include <openssl/bio.h>
          ^~~~~~~~~~~~~~~
compilation terminated.
scripts/Makefile.host:90: recipe for target 'scripts/extract-cert' failed
make[1]: *** [scripts/extract-cert] Error 1
Makefile:1097: recipe for target 'scripts' failed
make: *** [scripts] Error 2

調査した結果、次のモジュールをインストールすれば良いことがわかったのでインストールしました。

  • openssh-server
  • libssl-dev

【対策】
SSHサーバのインストール

sudo apt-get install openssh-server

参考情報:

【対策】
libssl-devのインストール

sudo apt-get install libssl-dev

参考情報:

【対策効果確認】
対策後、make modules_prepareコマンドが正常に終了しました。

koji@koji-VirtualBox:/opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/usr/src/kernel$ make modules_prepare
  HOSTCC  scripts/extract-cert
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/modpost.o
  CC      scripts/mod/devicetable-offsets.s
  UPD     scripts/mod/devicetable-offsets.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  VDSOA   arch/arm64/kernel/vdso/gettimeofday.o
  VDSOA   arch/arm64/kernel/vdso/note.o
  VDSOA   arch/arm64/kernel/vdso/sigreturn.o
  LD      arch/arm64/kernel/vdso/vdso.so.dbg
  VDSOSYM include/generated/vdso-offsets.h
koji@koji-VirtualBox:/opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/usr/src/kernel$

次のリンクを参照し、Makefile, hello.cを作成します。

作成したhello.cをビルドしカーネルモジュール(hello.ko)を作成します。

koji@koji-VirtualBox:~/hello_kernel_module$ make
make -C /opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/usr/src/kernel M=/home/koji/hello_kernel_module modules
make[1]: ディレクトリ '/opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/lib/modules/5.2.60-yocto-standard/build' に入ります
  CC [M]  /home/koji/hello_kernel_module/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/koji/hello_kernel_module/hello.mod.o
  LD [M]  /home/koji/hello_kernel_module/hello.ko
make[1]: ディレクトリ '/opt/windriver/wrlinux/19.45/sysroots/aarch64-wrs-linux/lib/modules/5.2.60-yocto-standard/build' から出ます
koji@koji-VirtualBox:~/hello_kernel_module$ ls
Makefile        hello.c   hello.mod.c  hello.o
Module.symvers  hello.ko  hello.mod.o  modules.order

Wind River Linuxのビルド

次はWind River Linuxのビルドをおこないます。
次のリンクの【GUIを備えたLinuxを生成するための設定】とおりに設定しビルドします。

bitbake wrlinux-image-glibc-std -c populate_sdk_ex

参考情報:

エラーとなってしまいましたが、最後までビルドを継続するようオプション(-k)を追加して再びビルドします。

koji@koji-VirtualBox:‾/wrlinux_bcm-2xx-rpi4_prj/rpi-gui$ bitbake wrlinux-image-glibc-std -c -k populate_sdk_ext

オプションの位置を変えてやってみます。

koji@koji-VirtualBox:‾/wrlinux_bcm-2xx-rpi4_prj/rpi-gui$ bitbake -k wrlinux-image-glibc-std -c populate_sdk_ext

エラーになりました。

Summary: 1 task failed:
  virtual:multilib:lib32:/home/koji/wrlinux_bcm-2xx-rpi4_prj/layers/oe-core/meta/recipes-support/boost/boost_1.71.0.bb:do_compile
Summary: There were 43 WARNING messages shown.
Summary: There was 1 ERROR message shown, returning a non-zero exit code.

dmesgで確認したところ、【Out of memory】が確認できました。

【対策】
10分毎にWidowsのフリーソフト・メモリクリーナの設定を40%掃除に設定しbitbakeしてみました。

【対策効果確認】
エラーは解消されませんでした。

【対策】
メモリクリーナの設定を70%掃除に設定しbitbakeしてみました。

【対策効果確認】
エラーは解消されませんでした。

【対策】
【ビルドの並列度】に関する設定を変更しbitbakeを実行してみました。
【BB_NUMBER_THREADS】は同時に処理するパッケージ数ということだそうです。
【PARALLEL_MAKE】はパッケージのビルドに割り当てるスレッド数ということだそうです。

conf/local.conf
BB_NUMBER_THREADS = "1"
PARALLEL_MAKE = "1"

【対策効果確認】
エラーは解消しませんでした。

参考動画: 再生時間帯 0:25〜1:45

【対策】
local.confの記述が間違っているかもしれないと思い、次のように修正しbitbakeコマンドを実行しました。

PARALLEL_MAKE = "-j 1"

【対策効果確認】
エラーは解消しませんでした。

他に何か対応策はないか調べていたところ次の概念を知りました。

  • OOM killer (out of memory killer)
  • オーバーコミット

参考情報

参考情報

デフォルト設定は次の値でした。

koji@koji-VirtualBox:~/wrlinux_bcm-2xx-rpi4_prj/rpi-gui$ cat /proc/sys/vm/overcommit_memory
0

これは次の意味になります。

  • オーバーコミット有効
  • 1回の malloc で確保できるのは実際に利用可能なメモリの大きさまで
koji@koji-VirtualBox:~/wrlinux_bcm-2xx-rpi4_prj/rpi-gui$ cat /proc/sys/vm/overcommit_ratio
50

こちらは次の意味になります。

  • メモリ容量の50%でOOM Killerが呼び出される

【対策】
次の値に変更してbitbakeします。

  • overcommit_memory 0 ⇛ 2(オーバーコミット無効)に変更
  • overcommit_ratioは50のままで変更なし

次のコマンドを実行し設定します。

% sudo su
# echo 2 > /proc/sys/vm/overcommit_memory

【対策効果確認】
Out of memoryは解消されませんでした。

【対策】
次の値に変更してbitbakeします。

  • overcommit_memory 0 ⇛ 2(オーバーコミット無効)に変更
  • overcommit_ratio 50 ⇛ 90(メモリ容量の90%でOOM Killerが呼び出される) ★今回の変更点

【対策効果確認】
Out of memoryは解消されませんでした。

【対策】
次の設定変更をおこないbitbakeします。

  • VirtualBoxのプロセッサ数を6から1にする。
  • overcommit_memory 0 ⇛ 2(オーバーコミット無効)に変更
  • overcommit_ratio 50 ⇛ 90(メモリ容量の90%でOOM Killerが呼び出される)
  • conf/local.conf は前の変更を適用している。 BB_NUMBER_THREADS = "1" PARALLEL_MAKE = "-j 1"

【対策効果確認】
bitbakeコマンドが成功しました。

次の階層にWind River Linuxのイメージファイルが作成できていることを確認できました(次のmicroSDへ書き込みで使うファイルのみ抜粋しています)。

koji@koji-VirtualBox:~/wrlinux_bcm-2xx-rpi4_prj/rpi-gui$ ls tmp-glibc/deploy/images/bcm-2xxx-rpi4/
 〜 略 〜
Image-bcm-2xxx-rpi4.bin
 〜 略 〜
bcm2711-rpi-4-b.dtb
 〜 略 〜
wrlinux-image-glibc-std-bcm-2xxx-rpi4.tar.bz2
 〜 略 〜

APSさんのリンクの【ビルド結果をmicroSDへ書き込み、起動する】のコマンドを実行し、Raspberry Pi 4 Model B起動用のmicroSDカードにファイルを書き込みます。

結果、冒頭のツイート画像のようにWind River Linuxが起動しました。
途中の作業工程で設定した【GUI】の画面になっています。

まとめ

いろいろとエラーは発生しましたが結果としてLinuxを構築することができました。
APSさんの記事、ネットにある先人の皆さんの情報共有に感謝です。
環境構築しなければわからなかった知識も得ることができました。

  • GUIをオフにする設定
  • OOM killer (out of memory killer) の概念
  • オーバーコミットの概念
  • ビルドの並列度に関する設定(BB_NUMBER_THREADS, PARALLEL_MAKE)
  • VirtualBoxなど少ないリソースでYoctoベースの組み込みLinuxをビルドする際に気をつける勘所

それと強く思ったのはYoctoベースの組み込みLinuxの構築はできるだけハイスペックPCでやったほうが良い、ということです^^;
長文を最後まで読んでいただきありがとうございました。
Linux環境構築を始めてみようと思っている方、悩んでいた方の参考になれば嬉しいです。

Linuxアドベントカレンダー2021 の25日目は@kentaostさんによる記事です。