PICでどのように使用malloc()
およびfree()
機能できますか?stdlib.h
ヘッダーを確認しましたが、言及されていません。MCC18を使用しています。
誰かがそれらを使用する必要がありましたか?
ライブラリをWindows XPからPICに移植しているので、それらが必要です。移植ガイドによると
オペレーティングシステムの特定の機能をPICの機能に適合させる
しかし、malloc()
とfree()
関数を「変換」する方法がわかりません。
PICでどのように使用malloc()
およびfree()
機能できますか?stdlib.h
ヘッダーを確認しましたが、言及されていません。MCC18を使用しています。
誰かがそれらを使用する必要がありましたか?
ライブラリをWindows XPからPICに移植しているので、それらが必要です。移植ガイドによると
オペレーティングシステムの特定の機能をPICの機能に適合させる
しかし、malloc()
とfree()
関数を「変換」する方法がわかりません。
回答:
多くのアプリケーションでは、メモリを割り当てる必要がありますが、その後に割り当てられたものを保持しながら、何かを解放する必要はありません。そのようなシステムでは、必要なことは、リンカーを使用して、使用可能なすべてのRAMを使用する配列を定義し、その配列の先頭にポインターを設定してから、簡単なmalloc関数を使用することだけです。
char * next_alloc; void * malloc(int size) { char * this_alloc; this_alloc = next_alloc; if((END_OF_ALLOC_SPACE-this_alloc)<サイズ) -1を返します。 next_alloc + =サイズ; this_allocを返します。 } void free(void * ptr) { if(ptr) next_alloc =(char *)ptr; }
素晴らしくて簡単で、割り当てがいくつあっても合計オーバーヘッドは2バイトだけです。ブロックでfree()を呼び出すと、そのブロックとその後のすべての割り当てが解除されます。
少し複雑な割り当てパターンは、2つのポインターを使用して処理できます。1つはメモリの下から上に移動し、もう1つはメモリの上から下に移動します。ヒープ内のデータが同種であり、外部へのすべての参照がどこにあるかがわかっている場合は、コンパクト化されたガベージコレクタを使用することもできます。
malloc()
マイクロコントローラでは一般的に「悪いこと」と考えられています。ただし、どうしても必要な場合は、サードパーティのバージョンを見つける必要があります。
運が良ければ、移植するコードはメモリブロックの再利用に依存しない場合があります。この場合、RAMバッファーにポインターを返し、要求されたブロックサイズだけポインターを進める単純なアロケーターを作成できます。
PCライブラリをマイクロコントローラーに移植する前に、このアプローチを使用して成功しました。
以下では、でアロケータを設定し、でmy_malloc_init()
メモリを割り当てますmy_malloc()
。my_free()
依存関係を満たすためにありますが、実際には何もしません。もちろん、最終的にはスペースが足りなくなります。
これを機能させるには、コードのワーストケースのメモリ要件を測定し(可能な場合はPCでこれを行う)、それにHEAP_SIZE
応じて設定する必要があります。ライブラリの動的メモリを必要とする部分に入る前に、を呼び出しますmy_malloc_init()
。再利用する前に、まだ何も指していないことを確認してくださいheap
。
uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;
void my_malloc_init(void)
{
heap_ptr = heap;
}
void *my_malloc(size_t len)
{
uint8_t *p = heap_ptr;
heap_ptr += len;
if (heap_ptr >= heap + HEAP_SIZE)
return NULL;
else
return p;
}
void my_free(void)
{
// do nothing
}
(注:現実の世界では、ポインターの配置、つまりheap_ptr
2バイトまたは4バイトで切り上げることを考慮する必要があるかもしれません)
別のオプションはmalloc()
、FreeListのように、通常提供されるよりも単純な割り当て構造を使用することですが、これでは可変サイズのブロックを割り当てることができない場合があります。
これはほとんどあなたの質問への答えではありませんが、動的メモリ割り当ては通常、小さなRAM環境ではオペレーティングシステムが存在しない場合(たとえば、マイクロコントローラの世界では)、埋め込まれた環境で利用できるヒープスペースは通常数百バイトで測定...
mallocとfreeの実装は、本質的には「フリーセグメント」構造のリンクリストのメンテナンスであり、ご想像のとおり、フリーセグメントに関連付けられたメタデータは、通常利用可能なメモリの量と比較しても実体的ではありません。 "動的メモリプールを管理すると、使用可能なリソースのかなりの量が消費されます。
C18標準ライブラリがmalloc
とをサポートしているかどうかはわかりませんfree
が、マイクロチップアプリケーションノートAN914に、独自のライブラリを実装する方法が示されています。
いずれにせよ、トーマスや他のポスターは、非常に小さなRAMスペースでPICに動的メモリを使用することは危険を伴うことを示唆しています。本格的なOSが提供するより高度な仮想メモリマネージャーがないため、連続した領域が急速に不足し、割り当ての失敗やクラッシュにつながる可能性があります。さらに悪いことに、それは確定的ではない可能性があり、デバッグするのはおそらく困難です。
あなたがやっていることが実行時に本当に動的に決定され(ほとんどの組み込みのものではまれ)、2、3の非常に特別な場合にのみスペースを割り当てる必要がある場合、私はmalloc
それfree
を受け入れ、受け入れられます。
さて、あなたのPICはメモリの点でどれくらい大きいですか?
mallocは、メモリを割り当てるための非常に非効率的な方法です。それに関する問題は、頻繁な解放とmallocによってメモリが断片化する可能性があり、メモリが数キロバイトしかない場合、割り当ての失敗がすべて一般的すぎることです。小さいチップまたは以前のPIC18を使用している場合、マイクロチップはmallocを実装するのが非常に困難(または場合によっては不可能)と見なしたか、十分に使用されなかったため、mallocをサポートしていない可能性があります。価値がある。それは言うまでもありませんが、非常に低速でもあります。すでに利用可能な静的バッファを使用する1サイクルと、mallocを実行するために数百から1,000サイクルのサイクルを調べています。
静的に割り当てたい場合は、sprintf関数のバッファー(存在する場合、約128バイト)、SDカードのバッファー(存在する場合)などを作成し、mallocが不要になるまで続けます。理想的には、それが絶対に必要な場所でのみ使用し、静的な割り当てを回避できないが、これらの状況は通常まれであり、おそらくより大きな/より強力なマイクロコントローラーを検討する必要がある兆候です。
また、PIC18で「オペレーティングシステム」を開発/移植し、マイクロコントローラーをサポートしている場合は、おそらく静的割り当てがサポートされています。たとえば、SQLite3は静的な割り当てをサポートしています-大きなバッファー配列を割り当て、マイクロコントローラー向けではないにもかかわらず、可能な場合はそれを使用します。そうでない場合は、小さなPIC18用に設計されていることを確認しますか?
私の知る限り、これを正しく行うには、ある種のメモリ管理ユニット(MMU)を備えたデバイスを実際に見ている必要があります。PIC18シリーズの動的割り当てメカニズムは存在しますが、実際にはそれほどしっかりしているわけではありません-PIC18シリーズの限界を押し広げるファームウェアに取り組んでいる誰かと言えば、あなたが得るつもりはないと言えるでしょう。あなたがメモリマネージャにすべてのオーバーヘッドを費やすなら、かなり大きなアプリケーションがあります。
より良い解決策:それが何をしているか、そしてなぜそれがダイナミックアロケーションを必要とするのかを理解しようとします。静的割り当てで機能するようにリファクタリングできないかどうかを確認してください。(これが単に不可能である場合もあります-ライブラリ/アプリケーションが自由にスケーリングする何かを実行するように設計されている場合、またはそれが受け入れることができる入力の量の限界がない場合)。あなたがやろうとしていることについては、代わりに静的割り当てを使用することが可能である(そしておそらく非常に簡単でさえある)ことに気付くかもしれません。