1. ホーム
  2. c

[解決済み】brk()システムコールは何をするのですか?

2022-04-07 02:01:36

質問

Linuxのプログラマーズマニュアルによると。

brk()およびsbrk()は、プログラムのブレークの位置を変更します。 は、プロセスのデータ・セグメントの終わりを定義します。

こっちのデータセグメントってどういう意味なんだろう?データセグメントだけなのか、データ、BSS、ヒープを合わせたものなのか?

wikiによると データセグメント :

データ、BSS、ヒープ領域を総称してデータセグメントと呼ぶことがあります。

データセグメントだけのサイズを変更する理由はないと思います。データであれば ビーエスエス とヒープを一緒にすると、ヒープがより多くのスペースを得ることになるので、理にかなっています。

そこで、2つ目の質問をさせていただきます。私がこれまでに読んだすべての記事で、著者はヒープが上向きに成長し、スタックが下向きに成長すると言っています。しかし、彼らが説明していないのは、ヒープがヒープとスタックの間のすべての空間を占めたときに何が起こるか、ということです。

解決方法は?

投稿された図では、"break"-で操作されるアドレスが表示されています。 brksbrk -はヒープ上部の点線である。

<イグ

あなたが読んだドキュメントでは、これが "データセグメントの終わりと説明されています。 mmap プログラム開始前にカーネルは、quot;text" と "data" ブロックをアドレスゼロから始まる RAM にロードし(実際にはアドレスゼロより少し上で、純粋に NULL ポインタが何も指していないように)、ブレークアドレスをデータセグメントの終端に設定するのです。 最初の malloc を使用することになります。 sbrk を使用して、ブレークアップを移動し、ヒープを作成します。 間に を使用すると、図に示すように、データセグメントの先頭と新しい高いブレークアドレスが表示されます。 malloc は、必要に応じてヒープを大きくするために使用されます。

一方、スタックはメモリの最上位から始まり、下に伸びていく。 スタックを大きくするために明示的なシステムコールを必要としません。スタックは、持てるだけの RAM が割り当てられた状態からスタートするか(これが従来のアプローチでした)、スタックの下に予約アドレスの領域があり、そこに書き込もうとするとカーネルが自動的に RAM を確保します(これが現代のアプローチです)。 いずれにせよ、アドレス空間の最下部にスタックに使用できる "guard"領域がある場合とない場合があります。 この領域が存在する場合(最近のシステムはすべてそうなっています)、それは永久にアンマップされます。 どちらかというと スタックやヒープがそこに成長しようとすると、セグメンテーションフォールトが発生します。 スタックがヒープの中に入り込んだり、ヒープがスタックの中に入り込んだり、どちらにしてもお互いのデータを上書きすることになり、プログラムがクラッシュしてしまいます。 もし、あなたがとても幸運なら、すぐにクラッシュするでしょう。

この図の512GBという数字がどこから来ているのか、よくわからないのですが。 これは64ビットの仮想アドレス空間を意味しており、そこにある非常にシンプルなメモリーマップと矛盾しています。 本当の64ビットアドレス空間は、このようなものです。

              Legend:  t: text, d: data, b: BSS

また、この図は、どのOSがどのように動作しているかを正確に示すものではありません(この図を描いた後、Linuxでは実行ファイルを私が思っていたよりもずっとアドレスゼロに近づけており、共有ライブラリも驚くほど高いアドレスに置いていることがわかりました)。この図の黒い領域はマッピングされていないもので、アクセスすると即座にセグメンテーションフォールトが発生します。 巨大 グレーの部分と比較すると 薄い灰色の領域は、プログラムとその共有ライブラリ(共有ライブラリは何十個もある)で、それぞれには 独立した テキストとデータのセグメント(および "bss" セグメントはグローバルデータも含みますが、実行ファイルやディスク上のライブラリで領域を占有するのではなく、オールビットゼロに初期化されます)です。 ヒープはもはや実行ファイルのデータセグメントと必ずしも連続しているわけではありません -- 私はそのように描きましたが、少なくともLinuxではそうではないようです。 スタックはもはや仮想アドレス空間の最上部に固定されておらず、ヒープとスタックの間の距離は非常に大きいので、それを越えることを心配する必要はないでしょう。

ブレークがヒープの上限であることに変わりはありません。 しかし、私が示さなかったのは、どこかの黒い場所で、何十もの独立したメモリ割り当てが mmap の代わりに brk . (OSはこれらを brk の領域で、衝突しないようにします)。