计算机执行一个可执行文件的流程


可执行文件的C源代码为:
main.c

#include <stdio.h>

int main(int argc, char *argv[])
{
	puts("Hello World");
	
	return 0;
}

编译完成后,生成一个可执行文件Demo。


执行流程如下:

  1. 双击可执行文件Demo,告诉操作系统我们要执行可执行文件。
  2. 操作系统接受到用户的请求后,就会根据用户提供的文件名,在磁盘上找到可执行文件Demo的相关信息。
  3. 找到信息后,会去检查该文件是不是一个可执行文件,检查完后,根据程序的首部信息确定代码和数据在这个可执行文件中的位置,并计算处它相应的磁盘块地址。
  4. 然后操作系统会创建一个新的进程,并将可执行文件Demo的格式映射到进程结构,表示由该进程来执行这个程序。
  5. 现在操作系统把控制权交给了调度程序,当调度程序选中了Demo程序,则操作系统给Demo程序设置CPU的上下文环境,并跳到程序的开始之处,准备执行这个程序。
  6. 当执行第一条程序的指令时,会发送缺页异常,这是因为程序在执行的时候,先要把代码和数据读入内存,CPU才能去执行,但程序Demo的代码和数据还没有读入内存,所以硬件机制会捕获出缺页异常,并把控制权交给操作系统。
  7. 操作系统管理了计算机系统的内存,比如在页式存储管理方式中,内存会有很多物理页面,内存管理模块会分配一页空闲的物理内存,并且根据前面计算出的磁盘块地址,把Demo程序的代码从磁盘读入内存,然后进行执行Demo程序。(有的时候程序很大,一页内存还不够,所以在这个执行过程中,会多次的产生缺页异常,导致多次从磁盘将代码读入内存)
  8. Demo程序执行puts函数,在标准输出上显示"Hello World",由于标准输出通常是显示器或者屏幕。所以实际上是一个系统调用,由操作系统完成这个功能,所以控制权又转给了操作系统。
  9. 操作系统找到要将字符串送往的显示设备,通常设备是由一个进程控制的,所以操作系统把要写的字符串给了这个进程。
  10. 控制设备的进程告诉设备的窗口系统它要显示字符串,窗口系统确定这是一个合法的操作,然后将字符串转换写成像素,将像素写入设备的存储映像区。
  11. 视频硬件将像素转换成显示器可接收的一组控制数据信号。
  12. 显示器解释信号,激发液晶屏
  13. 我们在显示屏看到了"Hello World"



页式管理机制通过页面目录,页面表,将每一个线性地址(虚拟地址)转换成物理地址,但并不是每一次CPU都能访问到相应的物理内存单元,因此这样映射便失败了,会产生缺页异常;

页错误,又叫页缺失,计算机系统术语,是指在引入分页机制的操作系统中,一个进程的代码和数据被放置在一个虚拟的地址空间中,地址空间按固定长度划分为好多页。同时,物理内存也按固定长度划分为好多帧。

因为物理内存小而硬盘空间大,为了在内存里放置更多的进程,操作系统的设计者们决定把页映射到内存帧或硬盘上的虚拟内存文件中。

进程的可视范围是它自己的地址空间,它并不知道某一页映射到内存里还是硬盘上,进程只管自己运行。当进程需要访问某一页时,操作系统通过查看分页表,得知被请求的页在内存里还是硬盘里。若在内存里,则进行地址翻译;若在硬盘里,则发生页缺失。操作系统立即阻塞该进程,将硬盘里对应的页换入内存,然后使该进程就绪(可以继续运行)。