一个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的文件格式,它的english name是Portable Executable File Format。
下面可要正式开始了。
一个microsoft的.exe程序的启动方法有很多,这里我们以双击App.exe图标启动为例(其他方法,我想也是一样的)。在补充一下,我所用的os是Windows2000Server,所以这里也主要讨论win2000下的应用程序,过要涉及较多关于NT内核,毕竟微软主推win2000/winxp和Unicode么。
一个microsoft的.exe程序的启动过程如下:
(1)当我们双击App.exe图标启动程序时,系统首先做什么呢,让我们先听一听侯捷是如何说的吧“执行起来的App进程其实是shell调用CreateProcess激活的”----"深入浅出MFC second 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环境,系统就直接加载文件的代码和数据并输入(import)该文件执行所需的dll函数。如果不是win32环境比如时os/2的.exe则先加载相应的环境子系统,载由该环境加载该文件的代码和数据以及该文件执行所需的dll函数。至于系统是如何知道文件的代码和数据以及该文件执行所需的dll函数所在的位置就需要你了解一下PE文件格式了,其实也很简单,PE文件拥有很多sections,数据和代码都放在不同的section里面,文件执行所需的dll也放在单独的section(.idata)里,这里就不详述了。而且在加载过程中涉及到有关虚拟内存,内存映射文件等很多较深的知识,我会在以后的系列文章中详细专题论述的。
(4)进程加载代码和数据完毕后,就开始创建线程来执行进程空间内的代码。进程是静态的,它只是线程的容器。一个进程至少因该有一个线程(main thread),其它线程都是主线程通过调用CreateThread函数创建的。线程也是核心对象,他的实际创建者是一个叫NtCreateThread的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,对应的入口点函数为wmain;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
分享到:
相关推荐
在Windows操作系统中,一个Microsoft的.exe程序文件的启动过程是一个复杂而精细的序列,涉及到多个操作系统层面的步骤。以下是对这一过程的详细解析: 首先,当用户双击一个.exe程序图标时,实际上是操作系统中的...
"Instsrv.exe"是一个小型的实用程序,由Microsoft Systems Internals开发,主要功能是将其他可执行文件安装为Windows服务。它的工作原理是向系统注册表添加必要的键值,使得指定的程序在系统启动时能够作为服务自动...
`srvany.exe`本身是一个空的服务宿主,不执行任何操作,但可以通过注册表配置来指向需要运行的其他程序。 使用`srvany.exe`的步骤如下: 1. **安装服务**:首先,用`instsrv.exe`将`srvany.exe`安装为一个新的服务...
Explorer.exe 是系统启动后第一个运行的程序,它负责构建用户界面,包括任务栏、开始菜单、文件夹视图以及桌面图标。用户通过这个界面来访问和管理设备上的文件和应用程序,进行基本的文件操作,如创建、打开、移动...
【inspect.exe 和 inspect32.exe】是微软提供的一对用于调试和分析Windows应用程序的工具,主要服务于开发人员和系统管理员。这两个程序可以帮助用户查看窗口、控件、消息以及线程等系统级别的信息,从而理解应用...
标题 "taskmgr.exe 文件下载" 暗示我们要讨论的是 Windows 操作系统中的任务管理器程序,这是一个核心系统工具,用于监控和管理运行在计算机上的进程、性能数据、应用程序和服务。taskmgr.exe 是该工具的可执行文件...
资源管理器是Windows操作系统中的一个核心组件,主要负责桌面环境、任务栏以及文件系统的用户界面。在某些情况下,用户或开发者可能需要通过编程方式来控制资源管理器的启动和关闭,例如进行系统维护、调试或者...
在压缩包子文件的文件名称列表中,有一个名为 "winhlp32.exe" 的文件。这同样是一个与帮助系统相关的文件,它用于打开传统的Windows帮助文件(.hlp)。虽然此问题主要涉及hh.exe和CHM文件,但如果你的系统同时遇到....
在这个过程中,LINK.EXE会处理数据和代码的定位,解决外部符号引用,以及添加启动代码和系统所需的头信息。通过链接器,开发者可以组织多个源文件,构建大型的程序结构。 EDIT.EXE则是一个简单的文本编辑器,用于...
`link.exe`是微软的链接器,它的主要任务是将由汇编器或编译器生成的多个目标文件(`.OBJ`)合并成一个可执行文件(`.EXE`)或者动态链接库(`.DLL`)。这个过程中,link.exe执行以下操作: 1. **定位地址**:为每...
标题中的“解决 sxstrace.exe无法启动”是一个关于在Windows操作系统中遇到的错误问题,而sxstrace.exe是一个系统工具,用于诊断和修复应用程序的 Side-by-Side (SxS) 组件问题。当我们尝试运行sxstrace.exe时,如果...
总的来说,这个压缩包提供了一个完整的汇编语言学习和开发环境,从编写源代码(使用文本编辑器),到汇编源代码(使用masm.exe),再到调试和链接生成的可执行文件(使用debug.exe和link.exe),都在DOSBox的模拟...
然而,当DLL文件丢失或版本不匹配时,依赖它的程序可能无法启动,这时Depends.exe就能派上用场。 Depends.exe 的主要功能包括: 1. **依赖分析**:它可以显示一个DLL或EXE文件所依赖的所有其他DLL文件,包括它们的...
LINK.EXE是微软的链接器,它的作用是将由MASM或者其他编译器产生的一个或多个目标文件(.OBJ)组合起来,形成最终的可执行文件(.EXE)。这个过程中,链接器会处理数据和代码的重定位,解决外部符号引用,以及添加...
1. 首先,你需要将 `instsrv.exe` 和 `srvany.exe` 文件放在同一个目录下。 2. 然后,打开命令行窗口,导航到该目录。 3. 接下来,运行 `instsrv.exe` 命令,指定服务的名称和 `srvany.exe` 作为服务的执行文件。...
InstallUtil.exe是.NET Framework自带的一个实用工具,主要用于安装和卸载由.NET框架创建的服务。使用步骤如下: 1. 创建C#服务项目:在Visual Studio中,选择新建项目,然后选择“Windows服务”模板。 2. 编写服务...
总结来说,这个"dosbox和link.exe和masm.exe以及debug.exe的整合版"是一个面向汇编语言开发者的实用工具包,它通过DOSBox提供了一个在现代Windows系统中运行和调试DOS时代汇编程序的平台,极大地便利了汇编语言的...
4. **安装系统补丁**:提供的文件"WindowsXP-KB896423-x86-CHS.exe"可能是一个针对此问题的微软补丁。安装这个补丁,按照提示操作,可能可以修复系统的漏洞或错误。 5. **扫描病毒和恶意软件**:使用反病毒软件进行...
Explorer.EXE 是 Windows 操作系统中一个非常重要的进程,它负责管理 Windows 图形壳,包括开始菜单、任务栏、桌面和文件管理。删除该程序将导致 Windows 图形界面无法使用。 一、Windows 资源管理器概述 Explorer...
标题中的"INSTMSIW.exe"是一个重要的关键词,它是指微软Windows操作系统中用于安装某些特定程序的一个执行文件。这个文件在Windows环境下通常与安装.NET Framework有关,因为.NET Framework的早期版本中包含了这个...