malloc / free以外のプログラムは、OSが何か他のものを提供する必要がありますか?
-
10-07-2019 - |
質問
作業中のOSのカーネルの設計に取り組んでいます(実際には「コア」とは異なるものと呼びますが、基本的には同じです)。マルチタスク、メモリ管理、その他の基本的なことを実行できない場合、OS自体の詳細は関係ないため、最初に作業する必要があります。 mallocルーチンの設計について質問しました。
malloc()はカーネル自体の一部(これに傾いています)またはプログラムの一部になると考えていますが、Cの独自の実装を作成する必要がありますどちらの方法でも標準ライブラリなので、mallocを記述できます。私の質問はこの点で実際にはかなり単純です、C(またはC ++)はそのヒープをどのように管理しますか?
理論の授業で私がいつも教えてきたことは、ヒープは、指定されたアドレスから始まり、多くの意味でスタックのように振る舞うメモリの断片であるということです。このようにして、グローバルスコープで宣言された変数が先頭にあり、さらに多くの変数が「プッシュ」されていることがわかります。それぞれのスコープで宣言されたヒープに追加され、スコープ外の変数は単にメモリ空間に残されますが、その空間は空きとしてマークされているため、必要に応じてヒープを拡張できます。
私が知る必要があるのは、Cが実際に動的に拡張するヒープをこのようにどのように処理するかということです。コンパイルされたCプログラムは、mallocルーチンを独自に呼び出して独自のヒープを処理しますか、それとも自動的に拡張するスペースを提供する必要がありますか?また、Cプログラムはヒープの開始位置をどのようにして知るのですか?
ああ、私は同じ概念が他の言語にも当てはまることを知っていますが、その言語に最も慣れているので、C / C ++で例を挙げたいです。私は自分でこのようなことを処理できると思うので、スタックなどの他のことも心配したくないです。
だから、私の本当の質問は、malloc / free(ページの取得と解放などを処理する)以外に、プログラムが何か他のものを提供するためにOSを必要とするのでしょうか?
ありがとう!
EDIT mallocルーチン自体の実際の動作よりも、Cがヒープに関連してmallocを使用する方法に興味があります。それが役立つ場合、私はこれをx86で実行していますが、Cはクロスコンパイラなので、問題ではありません。 ^ _ ^
さらに編集:用語が混乱している可能性があることを理解しています。私は、「ヒープ」がプログラムがグローバル/ローカル変数などを保存する場所でした。私は「スタック」を扱うことに慣れています。アセンブリプログラミングで、私はたぶんその代わりにそれを意味することに気づきました。私の側の少しの研究は、「ヒープ」がより一般的には、プログラムがそれ自体に割り当てた合計メモリ、またはOSが提供したメモリのページの合計数(および順序)を指すために使用されます。
では、それを念頭に置いて、拡大し続けるスタックをどのように扱うのでしょうか? (私のC理論クラスは軽度に...欠陥があったようです。)
解決
malloc
は通常、ユーザー空間のCランタイムに実装され、特定のOSシステムコールに依存して仮想メモリのページにマップします。 malloc
および free
の仕事は、サイズが固定されているメモリ(通常は4 KBですが、場合によってはそれ以上)のメモリページを管理し、それらをスライスしてさいの目に切ることです。アプリケーションが使用できる部分。
たとえば、 GNU libc の実装を参照してください。
より単純な実装については、 MITオペレーティングシステムクラスを最後からチェックしてください。年。具体的には、最終的なラボの配布資料をご覧ください。 、および lib / malloc.c
をご覧ください。このコードは、クラスで開発されたオペレーティングシステムJOSを使用します。これが機能する方法は、マップされていない仮想アドレス範囲を探して(OSによって読み取り専用で提供される)ページテーブルを読み取ることです。次に、 sys_page_alloc
および sys_page_unmap
システムコールを使用して、ページを現在のプロセスにマップおよびマップ解除します。
他のヒント
問題に取り組む方法は複数あります。
ほとんどの場合、Cプログラムには独自のmalloc / free機能があります。これは小さなオブジェクトに対して機能します。最初(およびメモリが使い果たされるとすぐ)、メモリマネージャはOSにさらにメモリを要求します。これを行う従来の方法は、Unixバリアントのmmapとsbrk(Win32のGlobalAlloc / LocalAlloc)です。
Doug Leaメモリアロケーター( google:dlmalloc)メモリプロバイダー(OSなど)の観点から。そのアロケーターは非常に優れたものであり、すべての主要なオペレーティングシステムへのフックを備えています。高性能アロケーターがOSに期待することを知りたい場合、これがコードです。最初の選択です。
ヒープとスタックを混同していますか?
「メモリの拡大し続ける部分」、スコープ、および宣言されたヒープ上のプッシュ変数に言及しているので、お願いします。実際にスタックについて話しているように聞こえます。
自動変数の最も一般的なC実装宣言では
int i;
は通常、iがスタックに割り当てられることになります。一般的に、mallocは、明示的に呼び出すか、何らかのライブラリ呼び出しを実行しない限り、関与しません。
「エキスパートCプログラミング」をご覧になることをお勧めします。 Cプログラムが通常どのようにスタックとヒープを処理するかについての背景についてはPeter Van Der Lindenによって。
必読:Knuth-コンピュータプログラミングの芸術、第1巻、第2章、セクション2.5。そうでなければ、Kernighan&を読むことができます。リッチー" Cプログラミング言語"実装を確認します。または、Plauger" The Standard C Library"を読むことができます。別の実装を確認します。
コア内部で行う必要があることは、コア外部のプログラムで見るものとは多少異なると思います。特に、プログラムのコア内メモリ割り当ては仮想メモリなどを処理しますが、コード外のプログラムはコアが提供する結果を単に見るだけです。
仮想メモリ管理(ページング)について読んでください。 CPU固有であり、すべてのOSは、サポートされているすべてのCPUに対してVM管理を特別に実装します。 OSをx86 / amd64向けに作成している場合は、それぞれのマニュアルをお読みください。
一般に、Cライブラリは malloc
の実装を処理し、OSにメモリを要求します(匿名の mmap
を介して、または古いシステムでは sbrk
)必要に応じて。そのため、カーネル側でこれらの手段のいずれかを使用してページ全体の割り当てを処理する必要があります。
その後、空きメモリを断片化しすぎないようにメモリを空にするのは malloc
の役目です。ただし、この詳細については au fait ではありません。ただし、 arena という用語が思い浮かびます。参照を見つけることができる場合は、この投稿を更新します。
危険危険!!カーネル開発を試みることを検討している場合でも、リソースの費用と比較的限られた可用性に注意する必要があります...
再帰についての1つのことは、それが非常に高価であることです(少なくともカーネルランドでは)、単純にそのままの状態で続行するために記述された多くの関数が表示されないか、カーネルがパニックになります。
ここで私のポイントを強調するには(stackoverflow.comへ)、具体的にカーネルスタックオーバーフローに関するNTデバッグブログ
・x86ベースのプラットフォームでは、 カーネルモードスタックは 12K です。
・x64ベースのプラットフォームでは、 カーネルモードスタックは 24K です。 (x64ベース プラットフォームには AMD64を使用するプロセッサ を使用するアーキテクチャとプロセッサ Intel EM64Tアーキテクチャ)。
・Itaniumベースのプラットフォームでは、 カーネルモードスタックは 32K で、 32K バッキングストア。
それは本当に、全体ではありません;
通常の容疑者
1。スタックを自由に使用します。
2。関数を再帰的に呼び出します。
ブログを少し読んでみると、かなりユニークな一連の問題でカーネル開発がいかに難しいかがわかります。あなたは理論のクラスは間違っていませんでした、それは単純で、単純でした。 ;)
理論から出発するには->カーネル開発は、可能な限り context スイッチの重要な部分です(おそらく、ハイパーバイザーの相互作用をいくらか節約してください!!)。
とにかく、あなたの期待を決して仮定、検証、テストしないでください。