分类: 操作系统实现

本文只为整理思路,供自己日后参考。现在就从从一个执行文件a.out的运行开始,自上而下地分析linux是如何运行一个执行文件的。

1、首先,需要了解一下a.out这个目标文件。a.out在linux下是ELF(Executable Linkable Format)文件格式,该目标文件由一个文件头、代码段、数据段(已初始化)、从定位信息区、符号表及符号名字字符串构成,如下左图所示,经过链接后生成执行文件如下右图所示,需要说明的是1).bss段在目标文件和执行文件中并不占用文件的空间,但是它在加载时占用地址空间;2)链接后各个段在虚拟空间上的地址就确定了,并且linux下,ELF可执行文件默认从地址0x080480000开始分配。

               

我们知道在linux下运行一个程序只要在shell中执行 ./a.out 这个命令就OK了,剩下的事情操作系统会替我们完成。但是操作系统到底做了什么,它是怎么做的呢,接下来就来解析一下。

2、linux系统中每个程序都运行在一个进程上下文中,这个进程上下文有自己的虚拟地址空间。当shell运行一个程序时,父shell进程生成一个子进程,它是父进程的一个复制品。子进程通过execve系统调用启动加载器。加载器删除子进程已有的虚拟存储段,并创建一组新的代码、数据、堆、栈段,新的堆和栈被初始化为零。通过将虚拟地址空间中的页映射到可执行文件的页大小组块,新的代码和数据段被初始化为可执行文件的内容,最后将CUP指令寄存器设置成可执行文件入口,启动运行。

执行完上述操作后,其实可执行文件的真正指令和数据都没有别装入内存中。操作系统只是通过可执行文件头部的信息建立起可执行文件和进程虚拟内存之间的映射关系而已。现在程序的入口地址为0x08048000,刚好是代码段的起始地址。当CPU打算执行这个地址的指令时,发现页面0x8048000~0x08049000(一个页面一般是4K)是个空页面,于是它就认为是个页错误。此时操作系统根据虚拟地址空间与可执行文件间的映射关系找到页面在可执行文件中的偏移,然后在物理内存中分配一个物理页面,并在虚拟地址页面与物理页面间建立映射,最后把文件中页面拷贝到物理页面,进程重新开始执行。该过程如下图所示:

3、这里比较难理解的就是这个分页机制,讲到分页机制,就不得不提linux的分段与分页机制,这也是这篇文章的重点。我们先来看一张图:

这张图展示了虚拟地址进过分段、分页机制后转化成物理地址的简单过程。其实分段机制是intel芯片为兼容以前产品而保留下来的,然后linux中弱化了这一机制。下面我们先简单介绍一下分段机制:

分段提供了隔绝各个代码、数据和堆栈区域的机制,它把处理器可寻址的线性地址空间划分成一些较小的称为段的受保护地址空间区域。如果处理器中有多个程序在运行,那么每个程序可分配各自的一套段。此时处理器就可以加强这些段之间的界限,并确保一个程序不会通过访问另一个程序的段而干扰程序的执行。为了定位指定段中的一个字节,程序必须提供一个逻辑地址,该地址包括一个段选择符和一个偏移量。实模式下,段值还是可以看作地址的一部分,段值位XXXXh表示以XXXX0h开始的一段内存。而保护模式下,段值仅仅变成了一个索引,只想一个数据结构的一个表项,该表项中定义了段的起始地址、界限、属性等内容。cs、ds等寄存器中存的就是这个段选择符,用段选择符中的段索引在GDT或LDT表中定位相应的段描述符,把段描述符中取得的段基地址加上偏移量,就形成了一个线性地址。

得到了线性地址之后,我们再来看看分页机制如何把它转换成物理地址。处理器分页机制会把线性地址空间(段已映射到其中)划分成页面,然后这些线性地址空间页面被映射到物理地址空间的页面上。分页与分段最大的不同之处在于分页是用来固定长度的页面(一般为4KB)。如果仅适用分段地址转换,那么存储在物理内存中的一个数据结构将包含器所有部分。但如果适用了分页,那么一个数据结构就可以一部分存储在物理内存中,而另一部分保存在磁盘中。

处理器把线性地址转换成物理地址和用于产生页错误异常的信息包含在存储与内存中的页目录和页表中。也变可看作简单的4K为单位的物理地址数组。线性地址的高20位构成这个数组的引索值,用于选择对应页面的物理基地址。线性地址的低12位给出 了页面中的偏移量。页表中的页表项大小为32位。由于只需要其中20位来存放页面的物理基地址,因此剩下的12位可用于存放诸如页面是否存在等属性信息。如果线性地址引索的页表项被标注为存在,我们就从页面中取得物理地址。如果表项中不存在,那么访问对应物理页面时就会产生异常。

页表含有2^20(1M)个表项,而每项占用4个字节。如果作为一个表来存放的话,最多将占用4MB内存。因此为了减少内存占用量,80x86适用了两级表。由此,高20位线性地址到物理地址的转换也被分成两步进行,每部适用其中10个比特。

第一级表称为页目录。它被存放在1页4k 页面中,具有2^10(1k)个4字节长度的表项。这些表项指向二级表。它们由线性地址最高10位作为引索。

第二级表称为页表,长度也是1个页面。线性地址高10位获取指向第二级页表的指针,再加上中间10位,就可以在相应页表中获得物理地址的高20位。而为地址的低12位就是线性地址的低12,这样就组成了一个完整的32位物理地址。分段、分页的整个过程可见下面这张图:

一个操作系统的实现(1):分析linux下如何运行一个执行文件相关推荐

  1. 如何分析linux下的几种目标文件

    为什么80%的码农都做不了架构师?>>>    作者:snsn1984 本文中用到的命令: gcc -c addvec.c 生成可重定位目标文件addvec.o readelf ad ...

  2. linux建立phyon文件,PyInstaller 来建立Linux下的Python独立执行文件

    以下内容假定已安装好Python 2.4/2.5 一.下载并编译pyinstaller(只需做一次,以后可直接做第二步) 1.下载pyinstaller,现在的版本是1.3 (1)wget http: ...

  3. linux下最简单多线程单文件socks5代理proxy服务器程序(仅一个c文件,带详细注解)

    2020.9.11 网上看的都比较复杂,GITHUB找了一个多线程的相对简单的MicroSocks项目,花了几周时间(没办法,菜鸟一个)改了一下,改成单文件,测试OK. /* wxl_socks5_p ...

  4. Linux 下查看某一个程序所使用的内存方法介绍

    Linux 下查看某一个程序所使用的内存方法介绍 在 Linux 上进行开发和运营维护的时候,免不了要查看某一个程序所占用内存的情况.常用方法总结如下(注意第四种方法): 第一种:ps -aux | ...

  5. 手把手教你如下在Linux下如何写一个C语言代码,编译并运行

    文章目录 手把手教你如下在Linux下如何写一个C语言代码,编译并运行 打开Ubuntu终端 创建 helloworld.c 编译C文件 手把手教你如下在Linux下如何写一个C语言代码,编译并运行 ...

  6. Linux系统怎么吸引用户,Linux下如何增加一个系统用户

    Linux下如何增加一个系统用户 (2008-04-08 14:18:11) 标签: it 人邮的<Linux指令速查手册>相当不错,我跟我的朋友都有一本.拿着也方便.我这人,看到好书都这 ...

  7. linux如何创建目录结构,linux下怎么创建一个目录命令mkdir

    linux下怎么创建一个目录命令mkdir linux下用mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 命令格式: ...

  8. linux下并行运行脚本与让程序可靠运行

    1 使程序可靠运行 linux下远程进行命令执行时 可能由于网络问题,使得终端窗口被断开,导致终端内子命令执行失败. 为什么ssh断开后你运行的进程会退出呢? 因为所有进程都得有个父进程.当你ssh到 ...

  9. Linux 下固态硬盘恢复误删除文件

    首发地址:学习日记 Linux 下固态硬盘恢复误删除文件 – 学习日记 上次分享了一则Linux下恢复误删除文件的视频,有朋友在视频下方询问是否机械硬盘,由此引出今天这则Linux下固态硬盘恢复误删除 ...

最新文章

  1. 计算机入门新人必学,异世修真人怎么玩?新手快速入门必备技巧
  2. Codeforces Round #597 (Div. 2)题解A~D
  3. Linux命令行下关机【Ubuntu】
  4. nod找不到服务器,node.js – 带有nodejs child_process的ssh,在服务器上找不到命令
  5. xhprof在windows下面的安装和使用[上](windows版本)
  6. Apache HTTP Server 与 Tomcat 的三种连接方式介绍
  7. windows 运行banana
  8. VMware下Ubuntu 18.04关机后无法上网
  9. How to use neural network to realize logic 'and' and 'or'?
  10. Python 文字转语音(TTS)
  11. html5效果案例,10个优秀HTML5网站案例赏析
  12. 宇枫资本投资理财投资入门与技巧
  13. Windows 制作免安装的JAVA环境
  14. 在Android Eclipse 开发如何 使用 (*.aar)文件
  15. 我的面试心得与总结:BAT、网易、蘑菇街
  16. 51单片机c语言dac0832产生波形,基于51单片机的DAC0832波形发生器设计
  17. 基于微信失物招领小程序系统设计与实现 开题报告
  18. 直插DC插头内部分解,哪个是正哪个是负
  19. aws 亚马逊 服务器 运行docker run报错 Got permission denied while trying to connect to the Docker daemon socket
  20. 纵观消防设备电源监控系统

热门文章

  1. powerbi learning: look up table and data table
  2. 程序猿的英语之ielts indicator speaking test
  3. 计算机类期刊的影响因子
  4. 开源是项“全民工程”,揭秘开源团队的管理运作
  5. 优化数据库的注意事项
  6. 经典递归——斐波那契数列,汉诺塔
  7. WPF的ProgressBar进度条
  8. HDFS【2.5.1】系列1:HDFS的核心数据结构---元数据
  9. Android的一些疑问
  10. c语言数组与指针浅析