Linuxのスタックはどのデータ構造を使用しますか?

Linuxのスタックはどのデータ構造を使用しますか?

私はいくつかの場所を見ました。ここしかし、誰もスタック自体(「タスク」(プロセス/スレッド)がネストされた呼び出し情報などを格納する場所)を実装するために使用される構造について詳しく説明していません。リンクリスト、配列、または別のものですか?情報が見つからないようですが、図を見ると、常に先頭にヒープがあり、最後にスタックがある1つの大きなメモリブロック(仮想メモリ)として表示されます。しかし、これは私たちが扱っている仮想メモリであり、ページングなどの周辺のさまざまなデータ構造を持っています。もしそうなら、問題はこれらすべてに加えて、スタックの具体的な実装が何であるかです。私はこれがリンクリストであることに間違いないとは思わなかった。

その理由は、それぞれ独自のスタックを持つ複数のプロセスがある場合、これをどのように実行できるからです。

ここ私たちはある程度進展しているようです:

各プロセスには、現在のカーネルで実行されているときに使用する独自のスタックがあり、このスタックのサイズは8KBまたは(64ビットシステムの場合)16KBメモリです。スタックは直接マップされたカーネルメモリにあるため、物理的に連続している必要があります。

ベストアンサー1

スタックは実際に配列です。連続したメモリには複数の単語が含まれていますが、1つの重要な制限があります。一方の端でのみ増やして減らすことができます(したがって、FILO - 先入れ後出)。これもLIFOです。

アレイとの重要な違いは、プロセッサスタックが論理的にフレームに分割され(アレイとは異なり)、各フレームのサイズが互いに異なる可能性があることです。

各フレームには、次のような関数呼び出し時に保存する必要があるコンテンツが含まれています。

  • 呼び出された関数が呼び出し関数を続行するためにジャンプする戻りアドレス。
  • 戻り値を保持するスペースです。
  • 呼び出された関数に渡された各引数のコピー。
  • 別の機能でレジスタの最適化が妨げられないように、CPU レジスタをコピーします。

各レベルのすべてのパラメータとローカル変数に同じ名前を使用して関数がどのように再帰的であるか疑問に思った場合、その答えはすべて現在スタックフレームに相対的なアドレスを持っているということです。

スタックフレーム構造はプロセッサアーキテクチャごとに異なって定義され、最も自然な記憶方法が可能である。 「Linux」スタックはありません。 Intel、AMD、およびSparcにはそれぞれ独自の定義があります。プリコンパイルされたライブラリをダウンロードでき、ローカルコンパイラは自分のコードからそれを呼び出す方法を知る必要があります。

スタック自体も汎用データ構造です。たとえば、C、SQL、XMLなどのネストされたブロック構成を可能にする言語でソースコードを解析する場合、自分が属するブロックを積み重ねることは当然です。これを行うためにプロセススタックを使用したくないでしょう。解析中の項目には、再帰が必要な独自のコードではなくブロック構造があります。

各プロセスのスタックは、ユーザープロセスメモリの一部にすぎません。通常、ユーザーアドレス空間の範囲は-8MBから0、60MBまでです。スタックは-16で始まり、下に(ますます負になる)増加します。コンパイラ割り当てグローバルおよび静的メモリは0から始まり、上に上がり、ヒープ割り当ては固定メモリを超えて増加します。コードは保護上の理由から別の場所にあります。負のアドレス範囲をページングされたメモリにマッピングしても、仮想ストレージシステムに害はありません。

おすすめ記事