組み込みシステムのログ設計と性能の最適化

組み込み機器では、製品が市場に流通したのちに不具合が起こる場合もあります。原因をたどる手掛かりが、機器の残したログだけという場面も少なくありません。しかし、リソースが限られた組み込み機器で詳細なログを記録しようとすると、システムの動作速度やメモリ容量の圧迫を招きます。そのため、処理スピードを落とすことなく、限られたメモリに必要な情報を記録するための工夫が必要です。

本記事では、組み込みのログ設計の要点を、目的から実装、性能への影響、回収、信頼性まで解説します。

ログの目的と設計方針

ログ設計では、ログを残す目的の明確化、ログのレベルの決定、そしてログフォーマットの設計が重要です。

ログの目的

ログ設計でまず定めるのは、不具合解析の証跡を残し、事象を追跡できる手段の確保です。目的が曖昧なまま記録を始めると、必要な情報を残せない一方で、不要な情報を収集する結果となりかねません。この結果を防ぐためには、実機の動作履歴をたどれるよう、どの事象を残すかを設計段階で見極めることが欠かせません。この見極めが、品質向上の出発点になります。

ログレベルと出力制御

ログには重要度に応じた段階を設けます。一例としてZephyr Projectでは、エラー、警告、情報、デバッグの4つを定めており、深刻な異常から開発時の情報までを区別できます。すべてのログを常時出力すると、処理の遅延と可読性の低下を招きかねません。そこで有効なのが、ビルド時と実行時の2段階で出力範囲を切り替える方法です。デバッグ用ビルドでは詳細レベルまで、量産用では警告以上に絞り込むことは一例です。

ログフォーマットの設計

ログの1行ごとに、発生時刻のタイムスタンプ、出力元を示すタスクID、事象の種類を示すイベントIDを付与します。これらがそろうと、事象の前後関係を把握しやすくなります。解析ツールとの連携が容易になる点も見逃せません。記録形式には、読みやすいテキスト形式と、サイズが小さいバイナリ形式があります。容量に余裕のない機器にはバイナリ形式が適し、可読性重視ならテキスト形式が向くでしょう。バイナリ形式で保存した場合は、取得したログを解析できるようなツールを作る必要があります。

リングバッファによる効率的なログ実装

メモリが限られる組み込み環境では、ログをためる入れ物の構造が性能を左右します。その基本が、固定長メモリを循環して使うリングバッファです。

基本的な構造

書き込み位置(W)と読み出し位置(R)のポインタでデータを管理する、リングバッファの構造と動作例を示す図

リングバッファは、固定長のメモリ領域を円環状に循環させて使うデータ構造です。末尾まで書き込むと先頭へ戻り、最も古いログに新しいログを上書きしながら最新の記録を保ちます。動作の管理に用いるのは、書き込み位置を指すポインタと、読み出し位置を指すポインタです。実行中にメモリを動的に確保せずに済むため、制約の厳しい環境に適した方式といえます。

オーバーフロー時の設計

バッファが満杯になったときの動作は、設計時に決めておきます。古いログへ上書きを続けて最新情報を残すか、記録を停止して満杯までを保持するかの2択です。障害解析では発生直前のログが重要なため、上書きを基本としつつ大切な記録を守る工夫が求められます。ログが欠落した事実を見落とさないよう、欠落を検知するフラグを設けると安全です。バッファの大きさは、実機で観測したログ量を基に決めます。

マルチタスクと割り込みへの対応

複数のタスクや割り込みが同じバッファへ書き込む環境では、競合への対策が欠かせません。割り込み内でのログ出力は最小限にとどめ、ロックフリーの手法または短時間の排他制御で安全性を保ちます。割り込み内で長い処理をおこなうと、応答時間を保証するリアルタイム性が損なわれるためです。データ転送をCPUに代わって担うDMAを使えば、転送中のCPU負荷を減らせます。2つのバッファを交互に使うダブルバッファリングも、競合回避に有効でしょう。

ログ出力がシステム性能に与える影響

ログ出力は、CPUに負荷をかけるとともに、メモリの寿命を縮める処理です。システムへの影響を与えうることを理解して設計する必要があります。

ログ出力がシステムの性能を低下させる要因

ログを増やしすぎて割り込みへの応答が遅れ、制御が乱れる事例は珍しくありません。UART経由の出力はCPUへ負荷をかけ、フラッシュメモリへの書き込みは遅延を招く一因です。フラッシュには書き換え回数の上限があり、NAND型の寿命は数万回~十万回程度とされています。頻繁な書き込みは、この寿命を縮める大きな要因です。処理完了を待つ同期出力は待ち時間を生むため、出力量を絞る判断も要ります。

性能低下を防ぐ対策

性能への影響を抑える基本は、出力を非同期でおこなうことです。ログをいったんバッファにため、本来の処理を止めずに別のコンテキストで送信します。記録をバイナリ形式にすれば、転送するデータ量を削減できるでしょう。不要なログを除くフィルタリングや、データの圧縮も有効です。これらを組み合わせれば、性能への影響をさらに小さく抑えられます。

ログ出力の影響評価

感覚的な調整では、出力の過不足が生じがちです。対策の効果は数値で確かめます。まずログ出力にかかる時間を計測し、ボトルネックを特定します。次にCPU使用率やタスクの実行時間、割り込みの頻度やタイミングなどの指標で定量的に評価するのです。ログ出力の内容を調査することで、影響の大きさが見えてきます。その後、実機を用いた負荷試験による最終確認をおこないます。

ログ回収と運用の設計

ログは残すだけでは意味を持たず、回収と解析、運用を適切に行うことではじめて価値が生まれます。ログの設計には、現場での扱いやすさまで見据えることが欠かせません。

ログの回収方法

ログの回収手段は、UARTやUSB、ネットワーク経由での取得です。揮発性メモリ上のログは、電源が切れると消え、クラッシュ時に失われてしまいます。そこで、クラッシュ時のログは、電源を切っても残る不揮発メモリへ保存する仕組みが必要です。現場では開発者以外が扱う場面も多く、誰でも使える簡素な方法が求められます。

障害の再現と解析フロー

回収したログからは、機器の状態が遷移した履歴を復元できます。発生した状況や状態の変化を把握した上で、再現試験の結果と突き合わせることは原因特定の第一歩です。障害が起きた条件を絞り込めれば、根本原因にたどり着きやすくなります。

ログに記された情報の不足により原因究明に至らなかった場合は、不足した項目や内容を課題として整理し、次の設計改善へ生かしましょう。ログの解析結果と不具合管理の情報、実施した対策を結び付けて記録することは、再発防止にも役立ちます。

ログの運用ルール

ログの書き方が担当者ごとに異なると、解析効率が落ちます。出力のルールを標準化し、チーム全体で書式をそろえることが欠かせません。ソフトウェアの版が変わるとログの書式も変わる場合があるため、版ごとの互換性の管理も必要です。取得手順を文書にまとめ、現場での対応フローを整えておけば、いざというとき迷いません。

ログの信頼性とセキュリティ

ログは解析の根拠となる記録です。内容が信用できなければ意味をなさないため、改ざんの防止、適切な保存、機密情報の保護が求められます。

ログの改ざん防止

保存したログが書き換えられると、解析や対応の誤りにつながりかねません。読み出しは何度でもおこなえる一方で、書き込み後に変更や上書きができない「WORM」を用いることで、意図しない上書きを防げます。

ハッシュ値や署名の付与も、有効な方法です。保存済みのログにこれらを付けておけば、回収時に改ざんの有無を検証できます。改ざんの検知により不正なデータを解析対象からはずすため、適切な調査と対応につながります。SIEMやログ管理システムの導入により、システムで対応する方法も選択肢の一つです。

ログデータの保存

ログを保存する領域は有限であり、すべてを無制限には残せません。そこで、どのログをどれだけの期間残すかを定めます。データのサイズ制限に応じて、保存期間を決めるとよいでしょう。重要度の低いログまで残すと容量を圧迫するので、重要なログを優先します。古いログや優先度の低いものから整理する方針も決めておくと安心です。

セキュリティ対策

ログを経由した情報漏えいは、見落とされやすい重大なリスクです。個人情報や機密情報は、ログに出力しないことを原則とします。やむを得ず扱う場合は、値を隠すマスキング処理が有効です。ログへアクセスできる人を権限で制限すれば、不正な閲覧や持ち出しを防ぎやすくなります。

組み込みソフトの世界 トップへ戻る