43

ここでは、Windows、Linux、OSX で実行可能ファイルを実行するとどうなるかをまとめたいと思います。特に、操作の順序を正確に理解したいと思います。私の推測では、実行可能ファイル形式 (PE、ELF、または Mach-O) がカーネルによってロードされます (ただし、ELFのさまざまなセクション(Executable とMach-O) は無視します)。 Linkable Format)とその意味)、そして参照を解決する動的リンカーがあり、次に実行可能ファイルの__init一部が実行され、次にメイン、次に 、__finiそしてプログラムが完成しますが、非常にラフだと思います、おそらく間違っています。

編集:質問は現在CWです。私はLinuxを埋めています。誰かがWinとOSXで同じことをしたいなら、それは素晴らしいことです.

4

5 に答える 5

35

もちろん、これは非常に高度で抽象的なレベルです。

Executable - No Shared Libary: 

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel allocates memory from the pool to fit the binary image into
  ->Kernel loads binary into memory
  ->Kernel jumps to specific memory address
  ->Kernel starts processing the machine code located at this location
  ->If machine code has stop
  ->Kernel releases memory back to pool

Executable - Shared Library

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel allocates memory from the pool to fit the binary image into
  ->Kernel loads binary into memory
  ->Kernel jumps to specific memory address
  ->Kernel starts processing the machine code located at this location
  ->Kernel pushes current location into an execution stack
  ->Kernel jumps out of current memory to a shared memory location
  ->Kernel executes code from this shared memory location
  ->Kernel pops back the last memory location and jumps to that address
  ->If machine code has stop
  ->Kernel releases memory back to pool

JavaScript/.NET/Perl/Python/PHP/Ruby (Interpretted Languages)

Client request to run application
  ->Shell informs kernel to run binary
  ->Kernel has a hook that recognises binary images needs a JIT
  ->Kernel calls JIT
  ->JIT loads the code and jumps to a specific address
  ->JIT reads the code and compiles the instruction into the 
    machine code that the interpretter is running on
  ->Interpretture passes machine code to the kernel
  ->kernel executes the required instruction
  ->JIT then increments the program counter
  ->If code has a stop
  ->Jit releases application from its memory pool

routeNpingme さんの言うとおり、CPU 内にレジスタが設定され、魔法が起こります!

更新: ええ、今日は正しくつづりができません!

于 2009-07-30T02:40:31.817 に答える
32

わかりました、自分の質問に答えます。これは段階的に行われ、Linux (およびおそらく Mach-O) に対してのみ行われます。個人的な回答に自由に追加して、賛成票を獲得してください (現在は CW であるため、バッジを取得できます)。

途中から始めて、残りは見つけ次第作ります。このドキュメントは、x86_64、gcc (GCC) 4.1.2 で作成されています。

ファイルのオープン、初期化

このセクションでは、カーネルの観点から、プログラムが実行される準備が整うまで、プログラムが呼び出されたときに何が起こるかを説明します。

  1. ELF が開きます。
  2. カーネルは .text セクションを探してメモリにロードします。読み取り専用としてマークします
  3. カーネルは .data セクションをロードします
  4. カーネルは .bss セクションをロードし、すべてのコンテンツをゼロに初期化します。
  5. カーネルは制御をダイナミック リンカ (名前は ELF ファイル内の .interp セクションにあります) に転送します。ダイナミック リンカーは、すべての共有ライブラリ呼び出しを解決します。
  6. 制御はアプリケーションに移されます

プログラムの実行

  1. 関数 _start が呼び出されます。これは、ELF ヘッダーが実行可能ファイルのエントリ ポイントとして指定しているためです。
  2. _start は glibc で (PLT を介して) __libc_start_main を呼び出し、次の情報を渡します。

    1. 実際のメイン関数のアドレス
    2. argc アドレス
    3. argv アドレス
    4. _init ルーチンのアドレス
    5. _fini ルーチンのアドレス
    6. atexit() 登録の関数ポインタ
    7. 利用可能な最大スタックアドレス
  3. _init が呼び出される

    1. call_gmon_start を呼び出して、gmon プロファイリングを初期化します。実行にはあまり関係ありません。
    2. __register_frame_info(eh_frame セクション アドレス、bss セクション アドレス) をラップする frame_dummy を呼び出します (FIXME: この関数は何をしますか? 明らかに BSS セクションからグローバル変数を初期化します)
    3. __do_global_ctors_aux を呼び出します。その役割は、.ctors セクションにリストされているすべてのグローバル コンストラクターを呼び出すことです。
  4. main が呼び出される
  5. メインエンド
  6. _fini が呼び出され、次に __do_global_dtors_aux が呼び出され、.dtors セクションで指定されているすべてのデストラクタが実行されます。
  7. プログラムが終了します。
于 2009-08-02T23:48:29.707 に答える
5

Windowsでは、最初に画像がメモリにロードされます。カーネルは、必要になるライブラリ(「DLL」を読み取る)を分析し、それらもロードします。

次に、プログラムイメージを編集して、必要な各ライブラリ関数のメモリアドレスを挿入します。これらのアドレスには、.EXEバイナリにすでにスペースがありますが、ゼロで埋められているだけです。

次に、各DLLのDllMain()プロシージャは、依存関係の順序に従うように、最も必要なDLLから最後まで1つずつ実行されます。

すべてのライブラリがロードされて準備が整うと、最終的にイメージが開始されます。現在何が起こるかは、使用される言語、使用されるコンパイラ、およびプログラムルーチン自体によって異なります。

于 2009-08-15T03:43:25.317 に答える
2

画像がメモリにロードされるとすぐに、魔法が引き継ぎます。

于 2009-07-30T02:31:38.893 に答える
0

正確な定義によっては、.Net や Java などの言語の JIT コンパイラを考慮する必要があります。技術的に「実行可能」ではない.Net「exe」を実行すると、JITコンパイラが介入してコンパイルします。

于 2009-07-30T02:06:05.240 に答える