組み込みシステムのメモリ管理

C 言語では、変数の 5 つのストレージ クラス、つまり、自動 (auto)、レジスタ (register)、外部リンクを伴う静的 (extern)、内部リンクを伴う静的 (ファイル内の静的)、コード ブロック スコープを伴う静的 (コード ブロック static) が定義されていますストレージ クラスが異なると、範囲と保存期間が決まります。

では、ストレージ クラスとメモリの間にはどのような関係があるのでしょうか?

保存期間の観点から、静的、自動、割り当てに分けられます。

静的ストレージ (静的) はコンパイル時に決定され、プログラムの実行時全体にわたって存在します。変数 (自動、レジスタ) はコード ブロックの実行時に生成され、終了時にクリアされます。動的メモリ割り当ては、malloc または関連関数の実行時に生成されます。が呼び出され、解放されると解放されます。割り当てと割り当て解除は線形ではないため、メモリの断片化が発生します。

スコープによって、プログラムのどの部分がどのデータにアクセスできるかが決まります。

組み込みシステムでは、メモリはヒープとスタックの形式で存在します。スタックはシステムによって自動的に割り当ておよび解放され、ヒープは開発者によって割り当ておよび解放されます。

データ構造のシナリオでは、ヒープとスタックは一般的に使用される 2 つのデータ構造を表します。

ヒープメモリ管理

C 言語でのメモリ割り当ての宣言は stdlib.h にあり、主に次の 4 つの関数があります。

マロック

コールク

再ロック

無料

どの関数がメモリに適用されるかに関係なく、完了後に free を使用して解放する必要があります。もちろん、Linux のようなシステムの場合、メモリを割り当てた後は、空きがなくてもプログラムは実行中に実行され、プロセスが終了すると、占有していたメモリはオペレーティング システムに返されます。これを行うサンプルコードをたくさん見ることができます。

ヒープ メモリの管理に関しては、組み込みプラットフォームやオペレーティング システムが異なれば、一定の違いがあります。

  • ベア メタル環境、特に stm32 ビットで表されるプラットフォームでは、使用される keil コンパイラは、MicroLIB ライブラリと呼ばれる C 標準ライブラリの簡易バージョンを実装します。大きなメモリ ブロックを割り当てる場合は、グローバル配列を使用し、複数回の適用と解放を避けることをお勧めします。
  • ucos には基本的なメモリ管理が既に備わっており、ヒープメモリの申請や解放は ucos が提供するインターフェース関数を使用します。
  • Linux のメモリ管理は非常に完全です。一般的に、グローバル データを使用できます。それが大きなメモリ ブロック (128KB 以上など) の場合、通常は mmap システム コールを介してマップされます。使用後は、ummap がメモリを解放します。

一般に、組み込みシステムは次のように分類されます。

  1. スタック: 関数のパラメータ値、ローカル変数値、リターンアドレスなどを格納するために、コンパイラによって自動的に割り当ておよび解放されます。その操作方法は、データ構造におけるスタックに似ています。
  2. ヒープ: 通常、プログラマによって動的に割り当てられ (mallo0 関数を呼び出し)、解放されます (free0 関数を呼び出し)。プログラマが解放しない場合、プログラムの終了時にオペレーティング システムによってリサイクルされる可能性があります。
  3. データ セグメント (データ): グローバル変数、静的変数、および定数を格納します。保存されたデータに応じて、データ セグメントは通常のデータ セグメント (静的に初期化されたグローバル変数または定数を保存する読み取りおよび書き込み可能/読み取り専用のデータ セグメントを含む) と BSS データ セグメント (初期化されていないグローバル変数を保存する) に分割できます。
  4. コードセグメント (コード): プログラムコードを格納するために使用されます。

したがって、一般に動的に適用されるのはヒープ メモリです。malloc を使用してメモリを割り当てると、メモリ サイズを保存および記録するためにさらに数バイトが割り当てられます。malloc によって割り当てられたメモリは、通常 memset を使用して初期化する必要があります。Calloc は割り当てられたメモリを 0 に初期化します。

Unix システムでは、メモリを割り当てるための alloca も提供されていますが、2 つ目は、ヒープから適用する代わりに、スタック フレームのサイズを増やしてスタックから割り当てる方法です。メモリを解放する必要はありません。

Linuxのメモリ管理

Linux のメモリ管理は、CPU とメモリ間の仮想メモリ管理を実装するために使用される MMU (メモリ管理ユニット) 上に構築されています。その主な機能は、アクセス制御およびキャッシュ管理機能を提供しながら、仮想アドレスを物理アドレスに変換することです。

メモリ管理の点では、MMU はページ テーブル (ページ テーブル) を通じて仮想メモリ管理を実装できます。ページ テーブルは、各仮想ページとそれに対応する物理ページの間のマッピング関係を記録するデータ構造です。CPU が仮想アドレスを発行すると、MMU はそれをページ テーブルから検索し、対応する物理アドレスに変換します。

4GB Linux は仮想メモリ管理テクノロジを使用しており、仮想メモリ テクノロジを使用して、各プロセスが相互に干渉しない仮想アドレス空間を持つことができます。

プロセスの初期割り当てと動作はこの「仮想アドレス」に基づいて行われ、プロセスが実際にメモリ リソースにアクセスする必要がある場合にのみ、仮想アドレスと物理アドレス間のマッピングが確立され、物理メモリ ページが転送されます。

仮想アドレスの利点

  • ユーザーが物理メモリ アドレスに直接アクセスできないようにし、一部の破壊的な操作を防止して、オペレーティング システムを保護します。
  • 各プロセスには 4GB の仮想メモリが割り当てられ、ユーザー プログラムは実際の物理メモリよりも大きなアドレス空間を使用できます。

4GB プロセス仮想アドレス空間は、3GB ユーザー空間 + 1GB カーネル空間の 2 つの部分に分割されます。

在Linux系统malloc ユーザー空間の仮想メモリを適用するために使用されます。 128KB 小さいメモリより小さいメモリを適用する場合は、割り当てられたメモリmallocを使用します 。 小さいメモリより大きいメモリ sbrk或brk を適用する場合は 、 メモリを適用する関数を使用します。128KBmmap

おすすめ

転載: blog.csdn.net/huntenganwei/article/details/131457986