操作系统学习之程序编译,链接,加载过程中的内存管理

程序从代码到可执行程序的过程:

代码-编译-链接-加载-执行

编译:编译器将源程序转换成可重定位代码。其有三个逻辑地址块:代码段(机器指令块),数据段(静态变量块),栈段(表示程序执行时使用的栈)。

编译器将所有的翻译过的机器指令写入代码段。考虑可重定位对象模块中的过程入口点,一般而言,编译器不能确定入口点的地址,因为目标过程可能在不同的可重定位模块中。例如,如果目标是库例程,如printf(),目标函数在系统软件建立时就编译好了。由于在编译时不知道目标模块的地址,所以目标函数不能被绑定,知道连接器将调用函数的模板与定义函数的模版链接为止。编译器将注明对每个外部地址的引用,使得链接器在链接时可以确定在绝对程序中外部引用的地址,并能将正确的地址填入代码中。

现在考虑静态变量在源程序中是如何处理的。(即使静态变量出了作用域,它仍保持最后一次存储的值)在编译时,编译程序生成代码在数据段为静态变量分配存储位置,然后指令中使用数据段中的相对地址引用变量。但是如果一个C语言的自动变量,编译器会产生代码在运行时栈中回到作用域,它不会保持旧的值。自动变量的存储空间会在程序执行时动态创建和释放,所以编译器会产生相对于栈的底部(而不是数据段地址)的变量指针。

链接:在链接时,每个可重定位对象模块的代码和数据段联合形成绝对程序。链接器会将所有的数据段联合成单个的数据段,并将所有的代码段联合成单个代码段。当数据段合并时,各静态变量的相对地址将改变。链接器然后重定位指令中的地址,使得它们引用合并的数据段中的新地址。链接器然后对入口点引用与合并代码段中定义的入口点地址进行匹配。在合并可重定位模块时,所有未定义的地址引用最后会被链接器发现,最终的组合模块包括了所有的程序文本和数据,这样每个数据的引用或程序入口点的引用都被解决了。绝对模块可以存储在文件(辅存)直到被执行。

加载:在加载一个绝对程序之前,存储管理器会分配一块主存给进程。然后加载器会将绝对程序和数据拷贝到分配的存储器中。注意,绝对模块的代码段部分中的地址需要再次调整。链接器将绝对程序中的所有地址设置成好像模块是从主存位置0处加载的。然而,模块现在是主存中的一个特定物理地址被加载的:存储块汇总的首地址需要由存储管理器指定。加载器转换每个内部逻辑主地址,使得它引用的是被分配的主存地址(而不是数据段或代码段的偏移量)。将程序使用的地址与主存中的物理存储位置相关联的过程称为地址绑定。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值