1. 前言  

  这里主要分析linux系统如何加载和启动一个可执行程序。一个源文件要想形成可执行文件,需要经过编译和链接才可以。也就是说源文件先要通过编译器编译成目标文件,然后利用链接器链接成可运行文件。这样做有助于程序的模块化管理,其示意图如下程序经过编译后的目标文件由代码段以及数据段等段组成,然后链接器将目标文件相同段合并,从而形成了可执行文件,其示意图如下所示:

这里需要指出,目标文件所有ELF格式在链接后也在最终的可执行文件中保存下来。可以利用readelf命令进行查看。

2 系统加载程序过程分析

  源文件被编译成可执行文件后,我们需要加载这个可执行文件进行执行。对于Linux下,系统是调用execve用来加载程序的运行。其具体的流程图如下

相关代码如下search_binary_handler寻找ELF文件解析器的关键代码如下

1 list_for_each_entry(fmt, &formats, lh) {
2         if (!try_module_get(fmt->module))
3             continue;
4             read_unlock(&binfmt_lock);
5             prm->recursion_depth++;
6             retval = fmt->load_binary(bprm);
7             read_lock(&binfmt_lock);            

其中注意load_binary这个调用函数,它启动了了load_elf_binary这个程序,具体是通过修改elf_fomat这个结构体实现的。相关代码如下所示

 1 static struct linux_binfmt elf_format = {
 2   .module     = THIS_MODULE,
 3   .load_binary    = load_elf_binary,
 4   .load_shlib = load_elf_library,
 5   .core_dump  = elf_core_dump,
 6   .min_coredump   = ELF_EXEC_PAGESIZE,
 7 };
 8
 9 static int __init init_elf_binfmt(void)
10 {
11     register_binfmt(&elf_format); //注册elf_format,这样解析器就可以调用合适的程序来解析elf格式
12     return 0;
13 }

3 实验

开始启动时出发sys_execve中断

最后修改IP(指令计数器指向可执行文件),通过readelf命令读取执行文件可以验证。这里映射地址是进程中的地址,并非实际内存中地址。

进程地址空间为

0x08048000 —— 0x0804c000

  

4 总结

通过这章学习了一个源文件如何编译成可执行文件,并且Linux如何加载这个可执行文件到进程的地址空间当中的。实验也验证了之前的分析,而这里execve最终实现方式是通过修改要指令寄存器实现的,即修改IP寄存器。虽然这里分析的只是elf文件的执行,但是这里看到程序中引入不同解释器解释不同文件的环节。通过这一机制可以有效增加支持的文件格式。这让我想起了那句计算机名言

Any problem in computing can be solved by another level of indirection.    ------David Wheel

转载于:https://www.cnblogs.com/qtalker/p/4439524.html

第七周 linux加载和启动一个可执行程序相关推荐

  1. 从内存中加载并启动一个exe

    从内存中加载并启动一个exe 文章作者:Idle_ (阿呆) 信息来源:[url]http://cnxhacker.net/article/show/2821.html[/url] windows似乎 ...

  2. Linux内核如何装载和启动一个可执行程序-----实验7

    2015108 李泽源 Linux内核如何装载和启动一个可执行程序 理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节: 编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程 ...

  3. linux 带ifdef运行程序_Linux内核如何装载和启动一个可执行程序

    郑斌+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验要求: 理解编译 ...

  4. Linux加载Linux的引导程序,Linux的引导-引导加载程序:LILO和GRUB

    打开计算机时,计算机执行存储在ROM中的引导代码,这些代码接下来尝试确定如何加载并启动内核.内核检测系统的硬件,然后产生系统的init进程,这个进程总是PID 1. 在出现登录提示符以前,要完成几项工 ...

  5. linux 加载u盘、光盘、软盘 mount使用指南

    <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  一.Linu ...

  6. 从设置、加载、启动看Xilinx FPGA配置流程

    尽管FPGA的配置模式各不相同,但整个配置过程中FPGA的工作流程是一致的,分为三个部分:设置.加载.启动. 本文引用地址: http://www.21ic.com/embed/hardware/pr ...

  7. 如何让linux加载当前目录的动态库

    debian从7.0开始支持multiarch,64位库的路径改到/usr/lib/x86_64-linux-gnu了,mint.ubuntu这些衍生版有没有跟着改我就不清楚了. deepin lin ...

  8. linux ntfs 密码,linux 加载ntfs和fat32分区

    原标题:linux 加载ntfs和fat32分区 纯手工打造每一篇开源资讯与技术干货,数十万程序员和Linuxer已经关注. 导读 关于加载ntfs和fat文件系统的文章极多,但写的不太明确,新手上路 ...

  9. 设置 COM加载项 启动时加载(及 解决 PDFMaker 文件遗失问题)

    设置 COM加载项 启动时加载(及 解决 PDFMaker 文件遗失问题) 我习惯于使用 Adobe Acrobat 的右键菜单文件合并功能合并 Word 文件,这个功能需要使用到 PDFMaker. ...

最新文章

  1. 深度学习在机器人视觉中的局限与优势(综述)
  2. Mongodb基础实践(二)
  3. 7 php程序的调试方法_PHP程序错误调试方法 让php显示错误提示
  4. (7)Python赋值机制
  5. Elasticsearch 实战经验总结
  6. DFT 与 ATPG综 述
  7. 做互联网的基因,互联网营销
  8. 禁止页面拖拽事件(数据什么的)
  9. docker-compose部署nacos 集群超过2个容器的问题
  10. android最贵的手机,2019翻盖手机排行榜_2019年最贵的手机有哪些?最贵手机排行榜...
  11. ceb2Pdf.exe实现ceb文件转pdf,内网离线安装wine(手动编译32位)实现在centos(linux)上运行window程序exe程序,解决wine : Z:\xxx EXE格式无效
  12. 球坐标系下拉普拉斯方程求解(Laplace equation)二
  13. 诸神战纪堕落天使java_诸神战纪-堕落天使路西法
  14. 数据质量第一步—数据监控
  15. JAVA实现经典游戏俄罗斯方块
  16. 用计算机玩游戏的视频教程,让桌面上同时操作游戏和显示视频的技巧-电脑教程...
  17. HDU6078 Wavel Sequence
  18. SFTP上传本地文件报错找不到文件或路径
  19. 【报错总结】无法连接Hive的MetaStore数据库
  20. 2021年小红书品牌经典爆文拆解

热门文章

  1. ORM框架之Spring Data JPA(一)Hibernate实现JPA规范
  2. [导入]asp.net2.0乱记(33)vista下使用vs2005及一些软件
  3. python棋盘覆盖_java实现的棋盘覆盖
  4. python xlrd模块_Python中xlrd模块解析
  5. junit可执行但控制层无法执行_springboot项目controller接口junit测试
  6. wps一直显示正在备份怎么办_做了一天的文档被误删?WPS这个功能随时准备帮你兜底...
  7. 【java学习之路】(数据结构篇)004.递归和二叉搜索树
  8. linux命令界面输入不了密码,如何在 Linux 中不输入密码运行 sudo 命令
  9. spark-sql配置并优化
  10. hive表列字段显示