execve関数
execve関数
1. execve()関数を呼ぶ
2. 引数で指定した実行ファイルからプログラムを読み出しメモリ上に配置(メモリマップ)するため必要な情報を読み出す 3. 現在のプロセスのメモリを新しいプロセスのデータで上書きする
4. プロセスを新しいプロセスの最初に実行すべき命令(エントリポイント)から実行開始する
プロセス数が増えるのではなく別のプログラムで置き換える
https://scrapbox.io/files/635501d1c063c6001d5c8c1c.png
execve関数の実現のため、実行ファイルは別プログラム起動に必要なデータを保持する
コード領域のファイルにおけるオフセット、サイズ、メモリマップ開始アドレス
データ領域における上記と同じ情報
最初に実行する命令のメモリアドレス
Linux の実行ファイルは通常 ELF=Executable and Linking Formt というフォーマットになっている https://scrapbox.io/files/635504340dc644001d4c79b0.png
readelf -hプログラムの開始アドレスを取得できる
命令の開始アドレスは 0x401050であることがわかる
コードでデータのファイル内オフセット、サイズ、開始アドレスは readelf -S コマンド
https://scrapbox.io/files/635504f707c00f001d9ed0e5.png
実行ファイルは複数領域に分けられそれぞれセクションと呼ばれる
セクションの情報は2行を1組として表示される
セクション名、メモリマップ開始アドレス、ファイル内オフセット、サイズなど
セクション名が.textであるものがコードセクション、.dataがデータセクション
数値はすべて16進数
https://scrapbox.io/files/635505feb6575c001deba267.png
プログラムから作成されたプロセスのメモリマップを確認して前述のアドレスからコード領域かデータ領域かメモリマップの範囲内に収まっていることを確認できる
別途、Cコンパイラオプションであった -no-pie は PIE=Position Independent Executable なプログラムにしないという指示 実行のたびに各セクションを異なるアドレスにマップするセキュリティ強化のカーネルの機能、ASLRを利用したプログラムをPIEと呼ぶ Ubuntu 20.04 の gcc ではデフォルトでPIEとしてビルドする execve()関数高速化:デマンドページング再び
デマンドページングはプロセスに新規メモリを割り当てるときだけではなくexecve関数発行直後も当てはまる 実行開始と同時にエントリポイントに対応するページがないためページフォールトが発生、物理メモリが割り当てられる、その後も別のページにアクセスするごとに同じことを繰り替えエス