程序在运行前需要经过以下步骤:
编译
用户源代码通过编译程序(Compiler)编译成CPU可执行的目标代码(Object Module)。
目标代码以0为基址顺序进行编址,符号名访问的单元被替换为具体的数据单元号,形成目标程序。
链接
编译后形成的一组目标模块(程序段)和它们所需的库函数通过链接程序(Linker)链接在一起,形成一个完整的装入模块(Load Module)。
链接过程中会合并段表和符号表,处理外部引用,并进行地址重定位(Address Relocation)。
装入(地址重定位)
装入程序(Loader)将装入模块装入物理内存。
物理内存是真实存在的内存条,装入模块虽然具有统一的地址空间,但需要确定装入内存的实际物理地址,并修改程序中与地址有关的代码,这一过程叫做地址重定位。
进程创建和管理
在多道程序环境下,要使程序运行,必须先为之创建进程。
创建进程时,操作系统会进行进程的创建,包括创建进程结构、虚拟地址空间、页表等。
装载器不会把代码直接装载到物理内存中,而是用一个页表把代码在硬盘上的位置记录下来,只有在真正运行的时候才会加载到内存里面。
操作系统进行进程调度,当轮到这个进程来的时候,才从装载器返回的入口点开始执行。
运行时栈分配
将代码和静态数据加载到内存后,给程序的运行时栈分配内存存放局部变量、函数参数和返回地址,并提供给进程。
其他初始化任务
操作系统还会执行一些其他的初始化任务,特别是与输入/输出相关的任务。
总结起来,程序在运行前需要经过编译、链接、装入、进程创建和管理、运行时栈分配和其他初始化任务等步骤。这些步骤确保程序能够从硬盘上的二进制代码变成在内存中执行的程序,并由操作系统进行调度和管理。