您的位置:首页 > 其它

从程序到进程:谈谈可执行文件是如何与进程相对应并最终被CPU执行的。

2011-07-31 16:08 381 查看
背景知识1:虚拟内存空间

从实模式到保护模式,从实际物理地址的访问到虚拟地址空间的访问。这一转变也导致了可执行文件的载入内存方式的转变,即:从简单的一次性装入(基本上就是一个拷贝、粘贴的过程),演变成由操作系统负责调度和装入内存。

而演变后的载入过程更多的是一种概念和逻辑,这体现在以下几个方面:

1:OS采用了分页的机制,程序的载入是分批进行的,即只有当程序运行到所需的代码或数据时,OS才从硬盘(交换区或磁盘文件中)上以页为单位将需要的内容真正加载到内存中。

2:当程序最初初始化并加载时,实际上主要的工作是加载一些初始化参数,包含程序信息的数据结构)到物理内存,而其他大部分数据和代码的“加载” 其实只是初始化了那些表示程序各段(代码段、数据段、BSS,堆,栈,常量区)信息的数据结构。

3:每个程序都会对应一个4GB的进程地址空间,更严格来说,是对应4GB中的一部分:即如下表所示的:用户方式的区域(略小于2GB)。从逻辑上来说,程序文件中的各段都会对应并载入到该 用户区。

虚拟地址空间如何分区(转载)

每个进程的虚拟地址空间都要划分成各个分区。地址空间的分区是根据操作系统的基本实现方法来进行的。不同的Wi n d o w s内核,其分区也略有不同。表 1显示了每种平台是如何对进程的地址空间进行分区的。

表1 进程的地址空间如何分区

分区
32位Windows 2000(x86和Alpha处理器)
32位Windows 2000(x86w/3GB用户方式)
64位Windows 2000(Alpha和IA-64处理器)
Windows 98
N U L L指针分配的分区

0 x 0 0 0 0 0 0 0 0 ——0x 0 0 0 0 F FF F

0 x 0 0 0 0 0 0 0 0 0 x 0 00 0 F F F F

0x00000000 00000000 0x00000000 0000FFFF

0 x 0 0 0 0 0 0 0 0 0 x 0 0 0 0 0F F F

DOS/16位Windows应用程序兼容分区







0 x 0 0 0 0 0 1 0 0 0 0 x 0 0 3 FF F F F

用户方式

0 x 0 0 0 1 0 0 0 0—— 0 x 7 F F E F F F F<将近2G>

0 x 0 0 0 1 0 0 0 0 0 x B F F E F F F F F

0x00000000 00010000 0x000003FF FFFEFFFF

0 x 0 0 4 0 0 0 0 0 0 x 7 F F F FF F F

64-KB禁止进入分区

0 x 7 F F F 0 0 0 0——0x7FFF FFFF

0 x B F F F 0 0 0 0——0 x B F F F F F F F

0 x 0 0 0 0 0 3 F F F F F F 0 0 00——0 x 0 0 0 0 0 3 F F F F F FF F F F



共享内存映射







0 x 8 0 0 0 0 0 0 0

文件(MMF)内核方式

0 x 8 0 0 0 0 0 0 0 —— 0 x F F F F F FF F<共2G>

0 x C 0 0 0 0 0 0 0 0 x F FF F F F F F

0x00000400 00000000 0xFFFFFFFFF FFFFFFF

0 x B F F F F F F F 0 x C 0 0 0 00 0 0 0 x F F F F F F F F

背景知识2:可执行文件的格式

可参考这篇文章,很详细:

https://www.ibm.com/developerworks/cn/linux/l-excutff/

背景知识3:进程的调度

现代的操作系统都是多任务的,所以,当前程序要被执行到,也必须等到OS将相应的时间片分配给当前程序所对应的进程。但是,这个过程对当前进程来说是透明的:它认为自己是至始至终都在独占CPU。

进入主题:

通过以上两个的说明,如果我们可以不考虑虚拟地址空间、按需加载以及地址重定向、多进程调度等细节(因为这部分完成是由OS负责,从程序本身来看,它看到的就是属于自己的一个连续的内存),在这块内存上,可执行文件的加载过程,其实质就是:根据文件格式中的描述信息,将每个段拷贝到相应的地址上,设置各种寄存器的初始化值,然后程序就可以开始执行了!

而这一过程就是实模式下的工作方式!

结语:

兜了一大圈仿佛又回到了最初,当然这其中蕴含了很多的相关技术和OS方面的知识。这些知识对于程序设计本身可能并没有直接的帮助,但是,这些背景知识却能为实现一个优秀的软件提供可靠的基础。了解了这些以后,我们才可以真正专注于软件开发本身,尤其是程序设计中的算法与数据结构方面的设计。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: