一个Microsoft的exe程序的启动过程.docx

上传人:b****5 文档编号:3241611 上传时间:2022-11-20 格式:DOCX 页数:28 大小:93.33KB
下载 相关 举报
一个Microsoft的exe程序的启动过程.docx_第1页
第1页 / 共28页
一个Microsoft的exe程序的启动过程.docx_第2页
第2页 / 共28页
一个Microsoft的exe程序的启动过程.docx_第3页
第3页 / 共28页
一个Microsoft的exe程序的启动过程.docx_第4页
第4页 / 共28页
一个Microsoft的exe程序的启动过程.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

一个Microsoft的exe程序的启动过程.docx

《一个Microsoft的exe程序的启动过程.docx》由会员分享,可在线阅读,更多相关《一个Microsoft的exe程序的启动过程.docx(28页珍藏版)》请在冰豆网上搜索。

一个Microsoft的exe程序的启动过程.docx

一个Microsoft的exe程序的启动过程

一个microsoft的.exe程序的启动过程

   学习windows 编程从mfc角度来说可分为两部分那就是WinMain函数以前的,和WinMain函

数以后的。

前者涉及很多windows操作系统内部的知识,后者么看mfc源码就可以了。

虽然大

多数程序不需要你了解太多关于os加载应用程序这方面的知识,但我认为能较深入了解

windows os的运行情况对程序员是很有帮助的。

   最近我正在研究一个microsoft的.exe程序的启动过程,这也是以上所说的关于os如何加

载程序的知识,它包括进程创建,主线程创建,PE文件加载,程序c运行时启动函数以及四种

main函数的调用等许多令我不得不静下心来好好思索的东东。

从mfc编程角度来说,这些都是

不得见的,不过了解这些对程序员编制好的windows程序是有好处的。

在平时的学习中我有

很多疑点,到底在桌面双击一个exe程序,os调用的第一个函数是什么?

甚至到现在我研究很

长时间后,还是得不到令我满意的答案。

不过在学习的过程中我还是有收获的,下面和大

家一起分享一下,我也把这段时间所学作一下总结。

   要了解一个.exe程序的启动过程就不得不了解一下有关操作系统方面的知识,such as“

进程,线程,虚拟内存"的基本的知识。

当然这里我就不详细介绍了,有兴趣的同学可以自己

去查一查这方面的资料。

在未真正开始之前,先统一一下本文出现的一些名词的含义:

   App.exe----------假定为应用mfc的AppWizard做出的一个SDI程序,App是它的名字。

可以把它看为一个标准的"hello mfc!

"程序。

   PE------------不要以为它是“体育课”的缩写呦。

它可是微软的标准win32可执行文件

.exe和动态链接库.dll的文件格式,它的Englishname是Portable Executable File Format。

 

   下面可要正式开始了。

    一个microsoft的.exe程序的启动方法有很多,这里我们以双击App.exe图标启动为例(

其他方法,我想也是一样的)。

在补充一下,我所用的os是Windows2000Server,所以这里也

主要讨论win2000下的应用程序,过要涉及较多关于NT内核,毕竟微软主推win2000/winxp和

Unicode么。

    一个microsoft的.exe程序的启动过程如下:

  

(1)当我们双击App.exe图标启动程序时,系统首先做什么呢,让我们先听一听侯捷是如何

说的吧“执行起来的App进程其实是shell调用CreateProcess激活的”----"深入浅出MFC se

cond edition" page39载。

很多书上都是如是说的,shell又名“命令解释器”,是win32操

作系统基于浏览器的一个32位用户接口,它是一个多线程的好例子,屏幕上每一个文件夹浏

览窗口都是它的一个线程。

它是操作系统引导时加载的系统进程,它具体表现为

windows explorer.exe。

explorer.exe是所有用户应用程序的创造者。

你完全可以将shell看成是所有应

用程序进程的父进程,就像桌面(desktop)可看成所有窗口的父窗口一样。

shell的用途很多

,如启动应用程序,管理文件系统,将应用程序与相应文件相关联等等。

我们常见的桌面上

的带有小箭头的快捷方式(shortcut)就是一个shell链接,shell负责管理一个叫"名字空间"

的类似文件系统似的“超文件系统”,它允许应用程序在任何地方在不知访问对象名字和位置

的前提下访问到这个对象,此类对象有:

文件,目录,驱动器,打印机以及网络资源。

而名

字空间就是shell把这些对象有层次组织起来的一个结构。

名字空间为用户和应用程序提供了

一种可靠和高效的方法来访问和管理对象。

好了不论它是什么,反正它调用了CreateProcess,一切就从这里开始了。

  

(2)CreateProcess这个函数可作了不少工作。

App进程由此诞生。

当CreateProcess这个函

数被调用,系统就会创建一个“进程内核对象”。

进程内核对象可以看作一个操作系统用来

管理进程的内核对象,它也是系统用来存放关于进程统计信息的地方(一个小的数据结构)

,其实它的真正创建者是一个叫NtCreateProcess的windows2000系统服务函数(也叫执行体服

务函数),他创建了进程内核对象供用户扩展。

进程内核对象的初始使用计数为1。

然后系统

为该进程创建4GB(=2^32)的虚拟地址空间(所谓虚拟就不是真的创建4GB的物理内存空间,这

些空间不是真在物理内存上).用于加载App.exe可执行文件和任何必要的dll文件的数据和代码。

  (3)下面概述一下系统的加载器(可称为loader)是如何加载这些东东的。

首先了解一下系

统为该进程创建4GB的虚拟地址空间是如何分配的,对于win2000/winxp来说,默认情况下每

个用户进程可以占有2GB的私有地址空间;操作系统占有剩余的2GB空间。

在32位x86系统上,

从0x00000000到0x7fffffff的空间中存放着 应用程序代码,全局变量,每个线程堆栈,dll

代码。

从0x80000000到0xc0000000的空间中存放着 内核和执行体,HAL(硬件抽象层),引导驱动程序

从0xc0000000到0xc0800000的空间中存放着 进程页表和超空间。

从0xc0800000到0xffffffff的空间中存放着 系统高速缓存,分页缓冲池,非分页缓冲池。

首先,CreateProcess打开应用程序文件(.exe),它先扫描该文件的文件头,该文件头里含有文

件能运行在那个环境之下,如果是win32环境,系统就直接加载文件的代码和数据并输入(im

port)该文件执行所需的dll函数。

如果不是win32环境比如时os/2的.exe则先加载相应的环境

子系统,再由该环境加载该文件的代码和数据以及该文件执行所需的dll函数。

至于系统是如

何知道文件的代码和数据以及该文件执行所需的dll函数所在的位置就需要你了解一下PE文件

格式了,其实也很简单,PE文件拥有很多sections,数据和代码都放在不同的section里面,

文件执行所需的dll也放在单独的section(.idata)里,这里就不详述了。

而且在加载过程中涉

及到有关虚拟内存,内存映射文件等很多较深的知识,我会在以后的系列文章中详细专题论

述的。

  (4)进程加载代码和数据完毕后,就开始创建线程来执行进程空间内的代码。

进程是静态的

,它只是线程的容器。

一个进程至少应该有一个线程(main thread),其它线程都是主线程通

过调用CreateThread函数创建的。

线程也是核心对象,他的实际创建者是一个叫NtCreateTh

read的windows2000系统服务函数。

一个线程其实只是一个线程核心对象和两个堆栈(一个核

心堆栈,用于线程运行在核心态;一个用户堆栈,用于线程运行在用户态),线程与进程类似

,也拥有线程核心对象计数和线程句柄,这里不详述。

线程用于描述进程中的运行路径。

当进程被初始化时,系统就要创建一个主线程。

该线程与c/c++运行时库的启动代码一道开始

运行,启动代码则调用进入点函数(就是我们的main函数,它也是主线程的进入点函数),并

且继续运行直到进入点函数返回并且c/c++运行时库的启动代码调用ExitProcess为止。

每个

线程都有自己的入口点函数,主线程入口点函数名字必须是main,wmain,WinMain或wWinMain

.而其他的线程入口点函数名字可使用任何名字。

每个线程函数必须有一个返回值,它将作为

线程的退出代码。

对于主线程来说,这个返回值将传给c/c++运行时库的启动函数。

  (5)c/c++运行时库的启动函数它其实是一个程序的真正调用的第一个函数,它是在程序链

接时由链接程序选择相应的启动函数并加到程序的开始处。

c/c++运行时库有四个版本的启动

函数,他们分别对应不同类型的应用程序。

比如,

需要ANSI字符和字符串的GUI应用程序的启

动函数是WinMainCRTStartup,其对应的进入点函数是

WinMain,

需要Unicode字符和字符串的GUI应用程序的启动函数是wWinMainCRTStartup,其对应

的进入点函数是wWinMain,

而需要ANSI字符和字符串的CUI应用程序(如控制台console程序)的应用程序的启动

函数是mainCRTStartup,对应的入口点函数为main;

需要Unicode字符和字符串的CUI应用程序

(如控制台console程序)的应用程序的启动函数为wmainCRTStartup,对应的入口点函数为wma

in;

c/c++运行时库的启动函数的功能如下:

以wWinMainCRTStartup(大多数运行在windows2000下的应用程序的启动函数都是它)为例。

负责:

  *检索指向新进程的完整命令行指针;

  *检索指向新进程的环境变量的指针;

  *对c/c++运行时的全局变量进行初始化;

  *对c运行期的内存单元分配函数(比如malloc,calloc)和其他低层I/O例程使用的内存栈进

行初始化。

  *为C++的全局和静态类调用构造函数。

当这些初始化工作完成后,该启动函数就调用wWinMain函数进入应用程序的执行。

当wWinMain函数执行完毕返回时,wWinMainCRTStartup启动函数就调用c运行期的exit()函

数,将返回值

(nMainRetVal)传递给它。

之后exit()便开始收尾工作:

  *调用由_onexit()函数调用和注册的任何函数。

  *为C++的全局和静态类调用析构函数;

  *调用操作系统的ExitProcess函数,将nMainRetVal传递给它,这使得操作系统能够撤销进

程并设置它的exit代码。

(6)至此启动函数的任务完成,至于中间wWinMain函数的运行过程看看mfc源码即可。

不过我还要提一下,wWinMain函数其实只是调用了mfc的AfxWinMain()函数,而一切的真正代码的运

行也是从AfxWinMain()开始的。

   以上只是粗略将一下一个microsoft的.exe程序的启动过程,其中有很多深奥的知识我只是提了一下,有些知识在以后的文章中还会陆续提到的。

                                                              bigwhite

                                                            2002.5.18

∙对我有用[0]

∙丢个板砖[0]

∙引用

∙举报

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1