次の方法で共有


高レベルのコア アプリケーション設計に関する提案

強固な基盤上に高レベル (HL) コア アプリケーションを構築するには、基本的なベスト プラクティスを使用する必要があります。 最も関連性の高い内容を次に示します。

高レベル (HL) コア アプリケーションは、Azure Sphere OS でコンテナー化して実行されます。 お客様のソリューションのコードレビューと設計レビュー中に、HL コア アプリケーションに関するいくつかの一般的な問題が見つかりました。 このトピックでは、これらの問題に対処するための設計の改善に関する提案について説明します。

一般的な基礎

HL コア アプリケーションを強固な基盤上に構築するには、基本的なベスト プラクティスを使用する必要があります。 最も関連性の高い内容を次に示します。

  • 初期化と終了: 常に Azure Sphere OS の SIGTERM シグナルを処理し、クラッシュ時またはエラー時に、終了時にすべてのハンドラー (周辺機器用など) を適切に初期化して破棄してください。 詳細については、 初期化と終了、 および 終了シグナルに関する GNU ドキュメントを参照してください。
  • 常に終了コードを使用します。 HL コア アプリケーションが終了時またはクラッシュ時に常に意味のあるリターン コードを提供することを確認する (SIGTERM ハンドラーを使用するなど) は、特にデバイスのクラッシュ ダンプ テレメトリからデバイスの動作を適切に診断するために不可欠です。 詳細については、「 終了コード 」および「 エラー データの収集と解釈」を参照してください。
  • エラーの場合は、デッドロック状態ではなく、常にアプリケーションの終了またはクラッシュが発生することを確認します 。詳細な障害復旧ロジックは、バグや動作が発生し、デッドロックや診断が困難な状態になる可能性があるため、逆効果になる可能性があります。 適切に設計された Azure Sphere アプリケーションでは、次の両方が発生するため、(ゼロ以外の終了コードを使用して) クラッシュまたは終了をデッドロックの可能性がある状況に常に優先する必要があります。
    • エラー テレメトリ、この問題の診断を有効にする
    • Azure Sphere OS によってアプリケーションが再起動されるため、動作状態に直ちに復旧する可能性があります
  • エラー処理とログ記録: 正確なエラー処理とログ記録は、品質の高いアプリケーション開発の中核をなしています。 クイック機能の実装は、コードのレイヤーに埋め込まれたままになります。その後、アプリケーションがフル スケールまで開発されるにつれて構築されます。 ベスト プラクティスの詳細については、「 エラー処理とログ記録」を参照してください。
  • ウォッチドッグとしてシステム タイマーを使用します。 最も重要なベスト プラクティスの 1 つは、重要なアプリケーションの状態を追跡し、デッドロックを検出し、それに応じて動作する "ウォッチドッグ タイマー" コールバック (ベアメタル MCU で使用できるハードウェアタイマーと同様) を実装することです (テレメトリの終了や送信など)。 詳細については、「 ウォッチドッグとしてシステム タイマーを使用する」を参照してください。
  • ベータ リリース ツールセットを対象に構築された運用アプリケーションをデプロイしないでください 。ベータ 版のサブセットが以降の OS バージョンで変更されないことを保証できないため、ベータ リリース ツールセットの使用はお勧めしません。 ベータ ツールセットは、公式の SDK リリースに先立って新機能をテストするためにのみリリースされます。

コンカレンシーの処理

  • 可能な限り EventLoop を使用します。 スレッドと同期オブジェクト (ミューテックス、セマフォなど) は、ほぼ同時タスクを実行するために使用されますが、組み込みシステム内では、システム リソースの使用に関してコストがかかります。 したがって、パフォーマンスを向上させるには、厳密にタイム クリティカルではなく、相互ブロックに敏感ではないタスクに対して、スレッドの代わりに epolls を使用することを検討してください。 関連するサンプルなど、EventLoop でイベントを監視およびディスパッチする方法については、「Applibs eventloop.h」を参照してください。
  • 同時実行タスクの効率を確認します。 ブロック操作とタイムアウトが epoll コールバック内で最小限に抑えられるようにすることが重要です。それ以外の場合は、他のすべての epoll コールバックが影響を受けます。
  • スレッドを使用する場合 (pthread): 呼び出しのブロックが避けられない場合など、特定のシナリオでは、スレッドの使用が有益な場合がありますが、通常、これらのシナリオの有効期間は限られており、特定のタスクのスコープを設定する必要があります。 たとえば、Azure Sphere OS (Linux を実行している) が HL コア アプリケーションに IRQ を公開していない場合 (これは RT コア アプリでのみ使用できます)、epoll タスクと pthread タスクの組み合わせを使用すると、インターネットからデータをダウンロードする際のダウンストリーム シリアル通信などの処理に最適な場合があります。

大事な

Azure Sphere OS では、特にデバイス構成証明の実行、更新プログラムの確認、テレメトリのアップロード中に、タイムリーな操作が中断される可能性があります。 タイム クリティカルな制御タスクの場合は、これらを M4 コアに移動し、コア間メールボックスを介して適切なプロトコルと調整することを検討してください。 詳細については、 コア間通信のサンプルを参照してください。

これらの提案に加えて、 非同期イベントとコンカレンシーに関する Azure Sphere のドキュメントを参照してください。

接続の監視

適切に設計された高レベル (HL) コア アプリケーションでは、適切な接続正常性チェック タスクを実装する必要があります。これは、Networking_IsNetworkingReady API を利用してインターネット接続の状態を定期的にチェックする堅牢な状態マシン (たとえば、エポール タイマーを使用) に基づいている必要があります。 場合によっては、HL コア アプリケーションが状態に対処するために使用できる特定のネットワーク インターフェイスに関連する接続状態の詳細な状態が提供されるため、 Networking_GetInterfaceConnectionStatus関数を使用できます。ただし、これは 90 秒ごとに呼び出す頻度が高く推奨されないため、コストがかかります。

ステート マシン コールバックには、通常、次の属性が必要です。

  • 可能な限り迅速に実行します。
  • ポーリング間隔は、特定のアプリケーション シナリオと全体的なソリューション要件 (一定時間、増分遅延など) に基づいて慎重に設計する必要があります。
  • 切断が検出されたら、 Networking_GetInterfaceConnectionStatusを 1 回呼び出して特定のネットワーク インターフェイスの状態をログに記録すると便利です。これは、問題を診断し、UI (LED、ディスプレイ、ターミナルなど) を介してユーザーに通知するために使用できます。 この方法のサンプルは、Azure Sphere DHCP サンプルのメイン コードに記載されています。
  • HL コア アプリケーションでネットワーク通信を実行 (または関連付けられている) 他のすべてのタスクを停止するメカニズム (グローバル変数など) をアクティブ化し、接続が再確立されるまでリソース消費を最適化します。
  • cURLは最近、コールバックの動作と最適な練習を更新しました。 Azure Sphere では、古いバージョンのcURL動作が引き続き期待どおりに動作するように努力してきましたが、再帰コールバックを使用すると予期しないクラッシュ、接続の停止、潜在的なセキュリティの脆弱性が発生する可能性があるため、curl_multiを使用する際のセキュリティと信頼性に関する最新のガイダンスに従うことをお勧めします。 TimerCallback が 0 ミリ秒のタイムアウトで起動する場合は、再帰コールバックを回避するために 1 ミリ秒のタイムアウトとして扱います。 また、curl_multi_add_handleの呼び出しに続いて、少なくとも 1 回は明示的に curl_multi_socket_action を呼び出してください。

前の提案に加えて、電源管理の次のシナリオを検討する必要があります。

  • データを送信した後、Azure Sphere チップの電源を切る。 詳細については、「 Azure Sphere デバイスの Power Down 状態を管理する」を参照してください。
  • いくつかの問題は指数関数的なバックオフ タイムアウトの長さによって発生する可能性があるため、外部の停止やアプリケーションの制御を超えたその他の要因によって接続が不可能になった状況でバッテリをドレインしないように、合計アップタイムを追跡し、シャットダウン タイマーを妥当な制限に設定することが重要です。
  • 障害時の接続監視を制御する場合、Wi-Fi トランシーバーは、ネットワーク インターフェイスをwlan0無効にして電源を切ることができます (「Networking_SetInterfaceState」を参照し、次のチェックが再び接続されるまで待機し、約 100mW を節約します。

メモリの管理と使用状況

メモリ制約のあるプラットフォームでは、メモリ割り当てと割り当て解除が頻繁に実行されるアプリケーションによって、OS のメモリ管理が効率に苦労し、断片化やメモリ不足が過剰になる可能性があります。具体的には Azure Sphere MT3620 では、メモリ不足状態が発生し、Azure Sphere OS の cgroup OOM キラー が開始される可能性があります。

当然のことながら、アプリケーションは、初期の概念実証から始めて開発されることが多く、これはプログレッシブ リリースに必要な機能により包括的になり、最終的には最初に含まれていたマイナーな機能を無視します。 フィールドで分析される多くのシナリオに対して効果的であることが証明された提案と最適化を次に示します。

  • 特にメモリを集中的に使用する HL コア アプリケーション内では、「ランタイム アプリケーションの RAM 使用率の決定」で説明されている Azure Sphere API を使用して アプリケーション メモリの使用状況を追跡することが不可欠です。 通常、これはエポール タイマー ウォッチドッグで実装され、アプリケーションは適切な方法で再起動するために予期しないメモリ使用量に応じて反応します。たとえば、適切な終了コードを使用して終了します。

    Azure Sphere ギャラリーで公開されているヒープ トラッカー メモリ追跡ユーティリティを使用すると便利な顧客やパートナーがいくつかいました。 このライブラリは、既存の HL コア アプリケーションに透過的にリンクし、メモリ割り当てとそれに関連するポインターを追跡するため、メモリ リークとポインターの誤用のほとんどのケースを簡単に検出できます。

大事な

この方法では、明らかに説明されていないデバイスの応答不能や、多くの場合、フィールドから報告されるエラーを減らすことができます。 このようなエラーは通常、HL コア アプリケーションによって適切に処理されないメモリ リークまたはオーバーランによって引き起こされ、OOM キラーがアプリケーションのプロセスをシャットダウンします。 これにより、Azure Sphere OS がテレメトリを送信できないようにする接続の低下と共に、 診断は Azure Sphere OS の診断ログを取得することによってのみ検出できるため、潜在的なフィールド インシデントにつながる可能性があります。

  • メモリ制約のあるプラットフォームでは、特に頻繁に呼び出される関数内で、可能な限り動的メモリ割り当てを回避することをお勧めします。 これにより、ヒープのメモリの断片化と、後続のヒープ割り当てエラーの可能性が大幅に低下します。 また、一時的な作業バッファーを繰り返し割り当てることから、スタックに直接アクセスする (妥当なサイズの変数の場合)、またはグローバルに割り当てられたバッファーに直接アクセスするパラダイム シフトも検討してください。これにより、オーバーフロー時に (を通じて realloc) サイズが増加します ( 「動的コンテナーとバッファー」を参照)。 メモリをオフロードする必要がある場合は、M4 コア上の未使用のメモリ (それぞれ 256KiB を持つ Azure Sphere で使用可能なメモリを参照) を利用し、データ キャッシュ用の軽量 RT コア アプリケーションを使用することを検討してください。 最終的には、外部 SD カードまたはフラッシュを使用できます。 サンプルは、次のリポジトリにあります。

上記の提案に従うと、HL コア アプリケーションがライフサイクル全体でフル容量で動作するために必要なメモリを見積もり、予約するのにも役立ち、後で設計の最適化のためにアプリケーションの全体的なメモリ 占有領域をより適切に見積もることができます。 Azure Sphere OS と Visual Studio の機能など、HL コア アプリケーションでのメモリ使用量の最適化の詳細については、次の記事を参照してください。