本读书笔记从第六章开始,之前的内容会陆续补上。内容上主要对认为重要的内容进行记录,《程序员的自我修养》确实是一本好书,欢迎大家一起对书中的内容进行讨论。第六章的6.1-6.3节的内容总结如下:

书中前三节已经基本阐述清楚了可行性文件、进程虚拟地址空间与物理地址空间三者之间的关系。在此简单做一总结。程序要被运行,其代码与数据应被装载进入内存方可被执行。因此操作系统首先应建立可执行文件与虚拟地址空间之间的映射关系,即操作系统应该清晰代码与数据被放在了虚拟地址空间中的何处,此所谓可执行程序与虚拟地址空间之间的映射关系。而操作系统中同时运行多个程序,为使他们之间运行不互相干扰,因此不能让进程直接访问物理内存,而是由操作系统代为管理物理资源,当然这只是建立虚拟地址空间的原因之一,其他几点原因不清楚的同学,可参考操作系统理论的有关书籍。书归正传,正由于虚拟地址空间与物理地址的不等同,虚拟地址空间与物理地址空间同样存在某种映射关系,这两者这间的关系涉及操作系统的内存管理,在此不再展开赘述。

6.4 进程虚存空间分布

6.4.1 ELF文件链接视图与执行视图

6.4小节的主要内容就是阐述如何建立可执行文件与进程虚拟地址空间之间的关系,凭我们最简单的想法,由于可执行文件已经被组织成了一个个不同的段,因此可执行文件可以以段为单位直接与虚拟地址空间建立一一对应的关系,但由于虚拟地址空间是按照页进行管理,因此直接建立映射关系,会造成大量的内碎片。如果换个调度思考问题,操作系统装载可执行文件其实不需要关心可执行文件的内容,仅了解段的权限即可,即保证程序在运行过程中不被错误访问即可。基于以上想法,可采用的方法是将相同权限的“段(section)”合并为一,进而组织成为“节(segment)”。借用书中的一句话:“从链接的角度看,ELF文件是按'Section'存储的,从装载的角度看,ELF文件是按'Segment'划分的”。换句话说elf的文件内容就在那里不多、不少。在此还应理清一个概念就是虚拟内存区域(VMA,Virtual Memory Area),所谓VMA就是指可执行文件与进程虚拟地址空间的映射关系,上述映射关系作为一个数据结构保存在操作系统中。操作系统就是在此基础上,将权限相同的节映射进入一个VMA中。即“节”的组织是静态的,是存在于硬盘中的,而VMA的组织的动态的,是存在于内存中的。但上述概念不是绝对的,有关于这一部分内容的解释请见下一小节。

我们可通过实验的方式进一步理解这一概念,采用书中给出的实验,使用readelf -S与readelf -h命令分别查看可执行文件的内容。在此要补充一点知识,不可使用objdump工具查看elf文件的内容,objdump -h与readelf -s输出内容基本一致,但前者无法输出.rel开头的段和.shstrtab,.symtab,.strtab。readelf与objdump的详细对比请见这篇博客:http://my.oschina.net/kangchunhui/blog/152682

同时由于我的机器是64位,因此虚拟地址空间不是从08048000开始,通过实验对比可进一步验证“segment”与“section”是从不同角度来划分同一个ELF文件。

可执行文件与共享库文件均有程序头表(Program Header Table),由于目标文件不需要被装载,因此不需要程序头表。结构体Elf32_Phdr 中记载了程序头表中的内容,上述结构体同样存在于/usr/inclde/elf.h中。

6.4.2-6.4.3

在操作系统中VMA除了被用来映射可执行文件中的各个“Segment”外,操作系统通过使用VMA来对进程的地址空间进行管理。进程在执行过程中还需要堆、栈空间,事实上堆栈空间在进程的虚拟空间中的表现也是以VMA的形式存在的,很多情况下,一个进程中的栈和堆分别对应一个VMA。在linux下,可通过命令cat /proc/PID/maps 查看进程的虚拟空间分布。其中PID指进程ID,可通过命令./elf &命令查看,其中elf为可执行文件名。

关于进程虚拟地址空间的概念总结如下:

操作系统通过给进程空间划分出一个个VMA来管理进程的虚拟空间;基本原则是将相同权限属性的、有相同映像文件的映射成一个VMA;一个进程基本上可以分为如下几种VMA区域:

代码VMA,权限只读、可执行;有映像文件。

数据VMA,权限可读写、可执行;有映像文件。

堆VMA,权限可读写、可执行;无映像文件,匿名,可向上扩展。

栈VMA,权限可读写、不可执行;无映像文件,匿名,可向下扩展。

上一下节中提到的不绝对的概念是指,Linux的进程虚拟空间管理的VMA的概念并非与“Segment”完全对应,linux规定一个VMA可以映射到某个文件的一个区域,或者是没有映射到任何文件。

6.4.4 段地址对齐

通过前三小节的分析,我们已经基本了解了可执行文件与进程虚拟地址空间之间的关系。但仅靠上述映射关系还不够,因为虚拟地址空间是按照页进行管理的,而可执行文件仍然是按照节进行管理的,因此就需要把一个个不同的“节”装入内存“页”中。还是从最简单的想法出发,直接以节为单位,映射进入虚拟地址空间中的“页”。但虚拟地址空间是以页作为管理单元,因此直接映射的方法肯定会造成内碎片问题,虚拟地址空间中的内碎片映射到物理地址空间就造成了资源的浪费。因此为解决上述问题,有些UNIX系统采用了一个很取巧的方法,就是让那些各个段接壤部分共享一个物理页面,然后将该物理页面在虚拟地址空间中映射两次。上述方法的采用虽然造成了虚拟地址空间的浪费,但将可执行文件看作是一个整体,以“页”为单位对其进行划分。但在虚拟地址空间向物理地址空间进行映射时,由于减少了内碎片,因此就减少了对物理内存的浪费。

6.4.5 进程栈初始化 内容不多在此就不总结了。

6.5 Linux内核装载ELF过程简介

本小节主要介绍linux是如何装载并执行ELF文件的。

首先在用户层面,bash进程会调用fork()系统调用创建一个新的进程,然后新的进程调用execve()系统调用执行指定的ELF文件,原先的bash进程继续返回等待刚才启动的新进程结束,然后继续等待用户输入命令。

1)execve()系统调用的入口是sys_execve()。

2)sys_execve()调用do_execve()。do_execve()的主要功能是查找被执行文件,如果找到文件,则读取文件的前128个字节以判断可执行文件类型。

3)调用search_binary_handle()去搜索和匹配合适的可执行文件装载处理工程。比如ELF可执行文件的装载处理过程为load_elf_binary()。

4)以load_elf_binary()为例,该函数最为重要的一步是将系统调用的返回地址修改成ELF可执行文件的入口点,这个入口点取决于程序的链接方式,对于静态链接的ELF可执行文件,这个程序入口就是ELF文件的文件头中e_entry所指的地址;对于动态链接的ELF可执行文件,程序入口点就是动态连接器。

5)按照调用顺序逐级返回load_elf_binary()->do_execve()->sys_execve()。

由于已经将系统调用的返回地址改成了被装载的ELF程序的入口地址了。所以当sys_execve()系统调用从内核态返回到用户态时,EIP寄存器直接跳转到了ELF程序的入口地址,于是新的程序开始执行,ELF可执行文件装载完成。

《程序员的自我修养》读书笔记相关推荐

  1. 读书笔记 | 墨菲定律

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  2. 读书笔记 | 墨菲定律(一)

    1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...

  3. 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记

    <洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...

  4. 股神大家了解多少?深度剖析股神巴菲特

    股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...

  5. 2014巴菲特股东大会及巴菲特创业分享

     沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...

  6. 《成为沃伦·巴菲特》笔记与感想

    本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...

  7. 读书笔记002:托尼.巴赞之快速阅读

    读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...

  8. 读书笔记001:托尼.巴赞之开动大脑

    读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...

  9. 读书笔记003:托尼.巴赞之思维导图

    读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...

  10. 产品读书《滚雪球:巴菲特和他的财富人生》

    作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...

最新文章

  1. 模块的使用,包,及程序开发规范
  2. android桌面小组件开发_快使用Scriptable自己开发一个iPhone小组件吧
  3. 深入理解计算机系统:进程
  4. C++从0到1的入门级教学(六)——函数
  5. git如何切换分支_拜托,不要再问我Git分支如何使用
  6. maven pom.xml详解
  7. 【转】CSS3 圆角 阴影 渐变 透明 旋转等功能详述
  8. “ void 0”是什么意思? [重复]
  9. 图像处理领域的国际会议及期刊
  10. python入门指南txt-【杂谈】爬虫基础与快速入门指南
  11. Android APK反编译详解(转)
  12. FastReport问题整理
  13. 【NLP Subword】三大算法原理:BPE、WordPiece、ULM
  14. android apk 微信登入_Android集成微信登录的步骤详解
  15. 异速联:解决打印样式个性化设置
  16. 视频录制软件进行电脑屏幕录像的使用方法
  17. html页面如何嵌套if标签,IF嵌套10个以上
  18. 商业虚拟专用网络技术一
  19. 网易云音乐唱片机效果
  20. Office365离线安装包

热门文章

  1. oracle seq nextval,Oracle 中select XX_id_seq.nextval from dual 什么意思呢?
  2. Java中before用法_Java Year isBefore()用法及代码示例
  3. 高新技术企业到底有什么好处?
  4. I’ve Got Your Back(gammon)
  5. 详解 layout_marginTop 与 layout_marginBottom
  6. 解决移动端scrollTo({behavior: “smooth“})滑动效果失效的问题
  7. 专升本英语——词性的分类1《词》
  8. 看ChatGPT是如何教我爬取上千家上市公司的股票代码
  9. Linux 高级指令
  10. jquery 百度地图 搜索选址获取经纬度 点击任意点获取经纬度