19

ですから、来年大学で受講する組み込みシステムユニットでは、動的データ構造が組み込みシステムプログラムに含まれるのは悪いことであることがわかります。しかし、講義ノートはその理由には触れていません。

現在、私は中規模の組み込みシステムの「LURC」コントローラーに取り組んでいます。ほとんどの場合、AVR169MEGAの「Butterfly」デモボードの周辺機器を利用しています。サーボとESCを制御するために4つのPWM信号を生成しました。また、9セグメントのLCD画面を提供します。

キューよりも、USARTシリアルを介して受信される命令を保存するためのより良い方法を考えることはできません。特に、不明な量のデータが受信されるまで待つ必要がある場合:たとえば、LCD画面に表示する文字列。

では、組み込みシステムのマイクロコントローラーで動的データ構造を使用してみませんか?メモリが大幅に制限された環境にいて、mallocが成功していることを確認する必要があるというだけですか?

4

9 に答える 9

25

組み込みシステムでmalloc(または同等のもの)を使用しない理由はいくつかあります。

  • あなたが言ったように、あなたが突然記憶から自分自身を見つけないことが重要です。
  • 断片化-組み込みシステムは何年にもわたって実行される可能性があり、断片化のためにメモリの深刻な浪費を引き起こす可能性があります。
  • 本当に必要ありません。動的メモリ割り当てを使用すると、同じメモリを再利用して、さまざまな時間にさまざまなことを実行できます。組み込みシステムは常に同じことをする傾向があります(起動時を除く)。
  • スピード。動的メモリ割り当ては、比較的遅い(そして、メモリが断片化されるにつれて遅くなる)か、かなり無駄になります(たとえば、バディシステム)。
  • 異なるスレッドと割り込みに同じダイナミックメモリを使用する場合は、割り当て/解放ルーチンでロックを実行する必要があります。これにより、割り込みの処理に十分な速度で問題が発生する可能性があります。
  • 動的メモリ割り当てにより、特に組み込みシステムで使用可能な制限付き/プリミティブデバッグツールの一部では、デバッグが非常に困難になります。静的に割り当てを行うと、常にどこにあるかがわかります。つまり、何かの状態を調べるのがはるかに簡単になります。

何よりも、メモリを動的に割り当てないと、メモリリークが発生しません。

于 2009-11-12T23:00:56.450 に答える
5

さて、多くの小さなマイクロコントローラーには、MMUや、作業に適したヒープを備えたOSのようなものはありません。

そうする人にとっては、あなたが求めているメモリの量に正気を保つ限り、私はそれに関して大きな問題は実際には見られません。

ただし、多くの組み込みシステムはリアルタイムシステムでもあります。アプリケーションの実行にかかる時間に厳しい期限がある場合、動的割り当てで問題が発生します。ほとんどのヒープ実装は、実行時間があまり制限されていないアルゴリズムを使用します。一部の(おそらくまれな)インスタンスでは、実行に通常よりも時間がかかります。リアルタイムのヒープ実装がいくつかありますが、それらはあまり広く使用されていません。一般的なルールは、初期化後のハードリアルタイムシステムでの動的な割り当てまたは割り当て解除を回避することです。

于 2009-11-12T22:53:47.147 に答える
5

私の見解では、過去4年間で「埋め込まれた」の意味が広がったためです。

従来、組み込みデバイスにはマイクロコントローラーが搭載されており、通常はオペレーティングシステムは搭載されていませんでした。保護されたメモリはなく、シングルスレッドでした。たとえば、32KBしか使用できない場合、メモリが不足しやすいため、mallocedメモリには細心の注意を払う必要があります。したがって、一般的には、固定サイズのバッファーを使用してコードを記述し、mallocを使用したり、使用するたびに使用したりすることはありません。

ここ数年で、古いPentiumPCと同じくらい簡単に強力なシングルチップPCまたはマイクロボードとは何かを見てきました。RAMの価格は現在非常に安く、非常に小さいため、メモリの制限は以前とはまったく異なります。また、組み込みLinuxやWinceを実行することも多いため、ダイナミックメモリをより自由に使用できるようになりました。

これにより、Java、C ++、多くのスクリプト言語、およびバッファオーバーラン保護と例外処理を提供するその他の言語、およびその他の高級言語を含む、はるかに幅広い言語を使用できるようになります。だから本当に、それらの古い問題は以前のようではありません。

この新しい利用可能なハードウェアはすべて、新しい範囲の問題が発生しているのではないかと思います。

于 2009-11-12T23:04:45.230 に答える
4

組み込み環境自体の動的メモリには何の問題もありませんが、一般に、組み込み環境ではそれほど多くのことを購入することはありません。

私の意見では、リングバッファを使用することは非常に良い考えです(これはI / Oドライバなどの非常に一般的なデータ構造です)。そうすれば、何らかの理由でキューを処理できない場合でも、メモリ使用量は決定論的です。

一部のマクロを使用すると、コンパイル時に可変サイズの構造体を割り当てることができます。

例えば ​​-

    //we exploit the fact that C doesn't check array indices to allow dynamic alloc of this struct
    typedef struct ring_buf_t {
        int element_sz,
            buffer_sz,
            head,
            tail;
        char data[0];
    } ring_buf_t;

   #define RING_BUF_ALLOC_SZ(element_sz,n_elements) (sizeof (ring_buf_t) + \
                                                      (element_sz) * (n_elements))

    char backing_buf[RING_BUF_ALLOC_SZ (sizeof(type_to_buffer), 16)];

    //ring_buf_init() casts backing buf ring_buf_t and initialises members...
    ring_buf_t *ring_buffer = ring_buf_init (element_sz, n_elemements, backing_buf);

;

このパターンは、メモリ使用量が保証された動的にサイズ変更可能なバッファです。もちろん、他の種類のデータ構造(リスト、キューなど)も同じ方法で実装できます。

于 2009-11-13T03:34:06.130 に答える
3

私の印象では、組み込みシステムでは、使用可能なメモリの量を正確に把握しており、その100%を正確に使用できます。他の(同時に実行されている)プログラムのために少し残す必要はありませんが、101パーセントを与えるために利用できる仮想メモリもありません。したがって、キューの場合、(たとえば)981レコード用のスペースがあることを簡単に計算できます。だから私はそれらのレコードの配列を作成し、982番目のレコードが必要になった場合、私はうんざりしていて、正常に失敗する方法を見つけなければなりません。

于 2009-11-12T22:54:03.090 に答える
0

私は記憶の欠如と失敗したmallocの問題の両方を言うでしょう。このような障害からシステムを救済するためのOS/インターフェイスがないため、後者の方が問題になります。ヘッドレスで実行されている可能性のあるシステム全体を急停止させる可能性のある機能を使用することは非常に危険です(または、リセットを引き起こす可能性がありますが、それでも悪いです)。

于 2009-11-12T22:49:21.647 に答える
0

組み込みシステムの動的データ構造は、C++のポインターに少し似ています。(C ++の)ポインターは悪です。しかし、時にはそれらが唯一の選択肢です。時には彼らはそれほど邪悪ではありません。時にはそれらを完全に避けても大丈夫です。それらを使用する正当な理由がある場合、これを行うための「良い」方法と「悪い」方法があります。

静的に割り当てられた変数と配列は、動的に割り当てられたデータよりも、割り当てと割り当て解除がはるかに高速であり、アクセスも高速です。この回答を参照してください。

動的に割り当てられた(つまり、 malloc()edまたは同様の)データには、割り当てを追跡するためのスペースオーバーヘッドも必要です。少なくとも割り当てごとに数バイト-このスペースは組み込みシステムで非常に価値があります!

メモリリークは組み込みシステムでは大きな問題であり、何年にもわたって実行されることが予想される場合があります。この観点から、動的割り当てを回避することが賢明です。

組み込みデバイスは通常、かなり信頼できる仕様を持っています。あなたは転送速度が何であるか、あなたが情報をどれだけ速く扱うことができるかなどを知っています。あなたの例では、解決策は固定サイズのバッファを循環キューとして使用することです。デバイスが処理できる必要があるものを処理するのに十分な大きさのバッファを作成します(おそらく少しだけ多く)。到着するデータが多すぎる場合は、おそらくどこか別の場所での障害または干渉が原因であるため、そのすべてのデータを保持して使用しようとする意味はあまりありません。

于 2009-11-12T23:02:26.380 に答える
0

Atmel MEGA169についてはわかりませんが、169に関連していると思われるMEGA168には1024バイトのSRAMしかありません。また、プログラムROMは16kしかないため、最新のコンピューターに比べて比較的低速です。そのため、メモリ、プログラムサイズ、速度に制限があります。

私のAVRアセンブラープログラミングの経験では、PICにできるだけ多くの機能を詰め込むのに手間がかかります。動的データ構造を使用するために必要なオーバーヘッドの量(追加のメモリ使用、SRAMからデータをプルおよびプッシュするために必要な追加の命令、どの動的変数がどこにあるかを追跡し、「間の」変数が削除されたときにメモリブロックを移動します。 ..)メリットを正当化するだけではありません。

したがって、コンパイラがそれを実装している場合でも、パフォーマンスのために静的データ構造を使用します。

于 2009-11-12T23:05:48.667 に答える
0

組み込みシステムで動的割り当てを利用することは悪い考えではないと思います。避けなければならない点がいくつかあります。

  1. HEAPサイズに注意してください。MAX_HEAPリンカファイルに記載されている制限を超えると、ハードウェア例外が発生する場合があります。
  2. システムの起動後にエリアを割り当てると、時間に依存するタスクが遅れる可能性があります。したがって、初期化フェーズで必要な領域を割り当てる方が適切です。それはルールではなく、単なる提案です:)
  3. 動的割り当てなしで直面している問題を解決できるかどうか、もう一度考えてみてください。

また、動的割り当てはプログラミング言語の優れた機能の1つだと思います。したがって、それなしで適切に構造化されたアプリケーションを設計することは考えられません:)

于 2021-03-06T13:45:09.443 に答える