装载与软件体系结构
1. 装载
1) 进程的建立
a. 创建一个进程内核对象
当一个线程调用CreateProcess时,系统就会创建一个进程内核对象,其初始使用计数是1。该进程内核对象不是进程本身,而是操作系统管理进程时使用的一个较小的数据结构。可以将进程内核对象视为由进程的统计信息组成的一个较小的数据结构。
b. 创建一个独立的虚拟地址空间
我们知道一个虚拟空间由一组页映射函数将虚拟空间的各个页映射至相应的物理空间,那么创建一个虚拟空间实际上并不是创建空间而是创建映射函数所需要的相应的数据结构。
c. 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系
当操作系统捕捉到缺页错误时,它应知道程序当前所需要的页在可执行文件中的哪一个位置。这就是虚拟空间与可执行文件之间的映射关系。从某种角度来看,这一步是整个装载过程中最重要的一步,也是传统意义上“装载”的过程。很显然,这种映射关系只是保存在OS内部的一个数据结构。
d. 如果有动态链接的话,就需要进行DLL的映射追踪
e. 将CPU的指令寄存器设置成可执行文件的入口地址,启动运行(在此之后但在在main开始之前,C/C++运行时库要做的那些事情就是在“运行库”那一节中介绍)
2) 页错误
当将主程序映射如虚拟内存空间之后,exe一般会被放置到0x00040000的位置,这个时候,当CS:IP所指向的代码开端并且开始执行这个地址的指令时,发现0x00040000到0x00041000是个空页面,于是它就认为这是一个页错误。CPU将控制权交给OS,OS有专门的页错误例程来处理这种情况。这时候就会根据已经建立起来的虚拟空间与可执行文件的映射关系找到所需页面在可执行文件中的位置,然后再物理内存中分配一个物理页面,将进程中该虚拟页与分配的物理页之间建立映射关系(通过Memory Management Unit, MMU),然后把控制权再返回给进程,进程从刚才页错误的位置重新开始执行。
2. 计算机软件体系结构
整个软件体系中,位于最上层的是应用程序,比如我们平时用到的网络浏览器、Email客户端等。从整个层次结构上来看,开发工具与应用程序是属于同一个层次的,因为它们都使用一个接口,那就是操作系统应用程序编程接口(application programming interface)。应用程序接口的提供者是运行库,什么杨的运行库提供什么样的API,比如LINUX下的Glibc库提供POSIX的API;Windows的运行库提供Windows API,最常见的32位Windows提供的API又被称为Win32。
运行库使用OS提供的系统调用接口(System call interface,其实是一种中断,windows采用0x2E号中断,在eax寄存器中保存需要调用的中断处理程序的中断号,但是从Windows XP Sp2开始,Windows开始采用一种新的系统调用方式),系统调用接口在实现中往往以软件中断的方式提供。
操作系统内核层对于硬件层来说是硬件接口的使用者,而硬件是接口的定义者,硬件接口定义决定了OS内核,具体来讲就是驱动程序如何操作硬件,如何与硬件进行通信。这种借口往往被叫做硬件规格,硬件的生产厂商负责提供硬件规格,OS和驱动程序的开发者通过阅读硬件规格文档所规定的各种硬件编程接口标准来编写OS和驱动程序。
------------------------------------------------------------------------
email : aicrosoft1104@126.com
吃遍天下。