Linux下程序的加载、运行和终止流程

简介

用户在编写程序时都要定义一个main()函数作为程序运行的入口。程序开始 执行时就从这个函数开始。当这个函数返回时就表明程序运行结束了。可是用户编写的 程序要能正确运行远不是这么简单。比如,我们不禁要问main()是由谁调用 的呢?当从main()返回后又运行到哪里去了呢?C++程序中定义的全局对象 是如何构造的呢?又是如何析构的呢?如果程序是动态链接的,它所依赖的共享库是 如何加载进内存的?更复杂的是,共享对象中的全局对象是如何构造的和析构的呢? 要回答这些问题,就不得不弄清程序加载、运行和终止的整个流程,从中也可以知道 系统软件(包括操作系统、动态链接器、链接编辑器和编译器)为了支持用户程序的 正确运行做了多么复杂的工作。

为了支持用户程序的正确运行需要解决以下几个重要问题:

  • 加载用户程序以及它所依赖的所有共享对象;
  • 对用户程序和共享对象进行符号解析重定 位
  • 向用户程序传递环境变量和命令行参数。
  • 根据C++标准的规定,全局对象(包括用户程序和共享库中定义的)必须 在main()执行前初始化,并在程序结束时以相反的顺序析构。

 

为了理清这些问题,下面我们来分析Linux系统下程序的运行流程。

术语

程序头(Program Header)
程序头在[gabi]的 Program Header一节中定义,是ELF文件执行视图的重 要部分。它规定了ELF文件中的哪些部分段需要加载以及加载的地址以及是否需要动 态链接器等信息。若需要动态链接器,程序头中的 PT_INTERP指定了动态 链接器的路径
初始化代码和终止代码(Initialization and Termination code)
每个可执行文件和共享对象都有初始化代码和终止代码。初始化代码在用户程 序开始执行前执行。所有的共享对象的初始化代码在可执行文件获得控制权之前执 行。终止代码则在进程退出时执行,顺序与初始化代码执行的顺序相反。共享对象 的初始化代码和终止代码由动态连接器负责执行。( Initialization and Termination Functions, [gabi])
加载时重定位(Load-time Relocation)和运行时重定位(Run-time Relocation)
加载时重定位指在动态链接器加载对象文件后就进行的重定位,而运行时重定位 是指在用户程序已开始运行后在需要的情况下进行的重定位。PLT表的重定位就属于 运行时重定位。在P
  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值