プロセスが作成されると、このプロセスに 1 つのスタックが割り当てられることがわかっています。スタックのサイズは通常、Linux では 8 Mb です。私の質問は、このスタックがどこから割り当てられるのか??ユーザー空間からですか?それともシステム空間からですか?
4 に答える
まず、ページングとページ フォールトとは何かを理解する必要があります。x86ページングはどのように機能しますか?
カーネル vs プロセス メモリ
Linux カーネルは、仮想メモリの 2 つのゾーンを予約します。
- 1 つはカーネル メモリ用
- プログラム用の 1 つ
正確な分割は によって設定されCONFIG_VMSPLIT_...
ます。デフォルトでは:
32 ビットの場合:
- 下の 3/4 はプログラム スペースです
00000000
。BFFFFFFF
- 上位 1/4 はカーネル メモリです
C0000000
。FFFFFFFF
このような:
------------------ FFFFFFFF Kernel ------------------ C0000000 ------------------ BFFFFFFF Process ------------------ 00000000
- 下の 3/4 はプログラム スペースです
64 ビットの場合: 現在、実際に使用されているのは 48 ビットのみで、2 つの等しいサイズのばらばらのスペースに分割されています。Linux カーネルは以下を割り当てるだけです。
00000000 00000000
処理する下部008FFFFF FFFFFFFF
- カーネルの上部:
FFFF8000 00000000
toFFFFFFFF FFFFFFFF
このような:
------------------ FFFFFFFF FFFFFFFF Kernel ------------------ FFFF8000 00000000 (not addressable) ------------------ 008FFFFF FFFFFFFF Process ------------------ 00000000 00000000
プロセスのアドレス空間
プロセスの簡略化されたプログラム仮想メモリ:
------------------ <--- Top of the process address space
Stack (grows down)
v v v v v v v v v
------------------
(unmapped)
------------------ <--- Maximum stack size.
(unmapped)
-------------------
mmap
-------------------
(unmapped)
-------------------
^ ^ ^ ^ ^ ^ ^ ^ ^ ^
brk (grows up)
-------------------
BSS
-------------------
Data
-------------------
Text
-------------------
------------------- <--- Bottom or process address space.
スタック割り当て
カーネルは、各プロセスに属するページのリストを維持し、それをページングと同期させます。
プログラムがそれに属していないメモリにアクセスすると、カーネルはページ フォールトを処理し、何をすべきかを決定します。
- 最大スタックサイズを超えている場合は、それらのページをプロセスに割り当てます
- それ以外の場合は、プロセスに SIGSEGV を送信します。これにより、通常はプロセスが強制終了されます。
brk
とmmap
これらのシステム コールにより、プロセスは、単にスタックを下って segfault する代わりに、カーネルにメモリのチャンクを明示的に要求できます。
以下は、実用的な例ですbrk
: brk( ) システムコールは何をしますか?
この回答は、可能な場合にスタックを使用する利点を説明しています: x86アセンブリのレジスタで使用されるプッシュ/ポップ命令の機能は何ですか?
物理メモリ
カーネルとユーザー空間メモリの間に明確な分割はありません: Linux x86-64 の物理メモリでユーザー空間とカーネルの間に明示的な分割はありますか?
すべてのユーザー プロセスはユーザー空間のみに保持されるという概念を理解していただければ幸いです。システムコールを使用して、カーネルによっていくつかの作業が行われます。
スタック メモリは、メモリ内のプロセス コンテキスト領域の一部になります。つまり、ユーザー空間です。
プロセスが実行中であると仮定して、 で PID を取得しますps -ax
。1234 があなたの PID だとします。
cat /proc/1234/maps
その特定のプロセスのマッピングを提供します。
そのマップ ファイルで、stack
スタック マッピングを確認できます。
他の人が言ったように、スタックはユーザー空間に割り当てられます。ただし、これについて、特にそのサイズと成長について詳しく説明します。
8 MB は実際にはスタック サイズではなく、最大スタック サイズです。小さな部分が最初に割り当てられ、カーネルは必要に応じて (ページ フォールトの後) スタックを自動的に拡張し、スタック サイズの制限を超えないようにします。制限を超えるメモリ アクセスを行うと、セグメンテーション フォールトが発生します。ただし、この制限に達しない場合でも、スタックをいっぱいにするだけで物理メモリ (RAM + スワップ) を使い果たす可能性があることを意味します。
これは、 Linux でスタック割り当てがどのように機能するかに対する私の回答で示した参照です。: Mel Gorman の論文Linux Virtual Memory Manager の理解。特に、セクション 4.6.1ページ フォールトの処理を参照してください。例外として、「リージョンは無効ですが、スタックのような拡張可能なリージョンの横にあります」と、対応するアクション「リージョンを拡張してページを割り当てる」があります。D.5.2スタックの拡張も参照してください。
アプリケーションソフトウェアに必要なスタックメモリは、ユーザー空間から割り当てられます。