【问题标题】:What happens when you run a program?当你运行一个程序时会发生什么?
【发布时间】:2010-11-15 07:13:26
【问题描述】:

我想在这里收集在 Windows、Linux 和 OSX 上运行可执行文件时会发生什么。特别想了解一下具体的操作顺序:我的猜测是内核加载可执行文件格式(PE、ELF或Mach-O)(但我忽略了ELF的各个部分( Executable and Linkable Format)及其含义),然后你有解析引用的动态链接器,然后运行可执行文件的__init部分,然后是main,然后是__fini,然后程序完成,但我确信它非常粗糙,而且可能是错误的。

编辑:问题现在是 CW。我正在为 linux 做准备。如果有人想为 Win 和 OSX 做同样的事情,那就太好了。

【问题讨论】:

  • 只有我一个人,还是这个问题的范围太广了?
  • 我觉得不太宽泛,但应该是社区wiki
  • 如果我没有得到足够的反馈,我想给它一个赏金。如果是CW,我将无法做到。
  • 我同意它可能很广泛。事实是,我想为系统之间的比较奠定基础。我接受建议。

标签: linux execution


【解决方案1】:

这当然只是一个非常高和抽象的层次!

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 内部,奇迹发生了!

更新:是的,我今天拼写不正确!

【讨论】:

  • “内核将二进制文件加载到内存中->内核跳转到特定的内存地址”“内核从这个共享内存位置执行代码”我对此表示怀疑。内核非常小心要执行什么代码;通常,它不会执行用户空间代码。你所说的很容易被攻击者利用。 Stefano 的回答更有意义。
【解决方案2】:

好的,回答我自己的问题。这将逐步完成,并且仅适用于 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 中的 __libc_start_main(通过 PLT)将以下信息传递给它

    1. 实际主函数的地址
    2. argc 地址
    3. argv 地址
    4. _init 例程的地址
    5. _fini 例程的地址
    6. atexit() 注册的函数指针
    7. 可用的最高堆栈地址
  3. _init 被调用

    1. 调用 call_gmon_start 来初始化 gmon 分析。与执行无关。
    2. 调用 frame_dummy,它包装了 __register_frame_info(eh_frame 部分地址,bss 部分地址)(FIXME:这个函数有什么作用?显然是从 BSS 部分初始化全局变量)
    3. 调用 __do_global_ctors_aux,其作用是调用 .ctors 部分中列出的所有全局构造函数。
  4. main 被调用
  5. 主端
  6. _fini 被调用,然后调用 __do_global_dtors_aux 来运行 .dtors 部分中指定的所有析构函数。
  7. 程序退出。

【讨论】:

  • 我不知道您想了解多少细节,但我无法理解这一点,因为我不知道 ELF 是什么。 (好吧,无论是那个还是 linux 都非常与我想象的不同)
  • 一旦我有时间继续阅读我找到的文档,我将继续这部分。 ELF 是 Linux 下可执行文件的二进制格式。就像 win 中的 PE 和 OSX 中的 Mach-O
【解决方案3】:

在 Windows 上,首先将图像加载到内存中。内核分析它将需要哪些库(读取“DLL”)并加载它们。

然后它编辑程序映像以插入所需的每个库函数的内存地址。这些地址在 .EXE 二进制文件中已经有一个空格,但它们只是用零填充。

然后每个 DLL 的 DllMain() 过程从最需要的 DLL 到最后一个一个一个地执行,就像遵循依赖顺序一样。

一旦所有的库都加载完毕并准备就绪,最后会启动映像,现在发生的任何事情都取决于使用的语言、使用的编译器和程序例程本身。

【讨论】:

    【解决方案4】:

    一旦图像加载到内存中,魔法就会接管。

    【讨论】:

    • 如果你把它设置为“魔法”。 “更多魔法”打破了宇宙。
    【解决方案5】:

    嗯,根据您的确切定义,您必须考虑 .Net 和 Java 等语言的 JIT 编译器。当您运行在技术上不是“可执行”的 .Net“exe”时,JIT 编译器会介入并对其进行编译。

    【讨论】:

    • .Net 运行时是一个可执行文件......它运行整个虚拟环境并优化字节码的事实是无关紧要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多