有谁能讲讲 一个EXE 文件是怎样被WINDOWS 给执行的,比如它是怎么被加载的,是怎么被装入内存的,CPU是怎么处理的。

导读:
在< <深入浅出> >一书中,候先生对一个进程从诞生到死亡的流程进行了简单的阐述。虽然只有十几点,但对于初学者来说,能够完全理解其中的含义已经不是一件易事了。总结自己的一些经验,对候先生的阐述进行了一些扩充,希望对初学者有所帮助,也希望高手指正其中的错误或不妥之处。

**************************************************
我对一个PROCESS (例App.exe)的诞生/死亡的理解:

1.Shell调用CreateProcess启动App.exe

2.系统产生一个“进程核心对象”,计数值为1

3.系统分配4GB进程空间

4.系统载入器(loader)将EXE文件映象和所有需要隐式加载的DLL文件映象映射到进程地址空间中。在此期间,要完成模块基址重定位, IAT(import address table)表转向,并且分配EXE及DLL中的全局和静态变量空间。注意只是分配空间,并没有执行初始化(包括执行C++对象的构造函数,已初始化数据除外)。下表给出了一些常见的节名和内容

节名(Segment) 内容
.text 应用程序或DLL的代码
.bss 未初始化的数据
.rdata 只读的运行时数据
.rsrc 资源
.edata 输出名字表
.data 初始化的数据
.xdata 异常处理表
.idata 引入名字表
.CRT 只读的C运行时数据
.reloc 修正表信息
.debug 调试信息
.tls 线程局部存储

5.系统创建了进程的主线程(primary thread)

6.主线程为每个DLL调用_DLLMainCRTStartu() 函数。
当链接DLL时,链接器在生成的DLL文件映象中嵌入了DLL的进入/退出函数的地址。缺省时为,链接器假设进入函数名为:_DLLMainCRTStartup。该函数包含在C运行时库文件中,当链接DLL时被静态的链接到DLL文件的映象中。即使使用的是C运行时库的DLL版本,该函数也会被静态的链接。
当DLL文件被映射到进程地址空间时,系统实际调用的是该函数_DLLMainCRTStartup, 而不是你的DLLMain函数。该函数执行:
a.初始化C运行时库。
// Do runtime startup initializers.
_initterm( &__xi_a, &__xi_z );
b.确保收到DLL_PROCESS_ATTACH通知时,DLL的所有全局或静态C++对象都被初始化。
(调用C++对象的Constructor函数)
// Do C++ constructors (initializers) specific to this DLL
_initterm( &__xc_a, &__xc_z );
c.完成初始化后,该函数调用你的DLLMain函数。
retcode = DllMain(hDllHandle, dwReason, lpreserved);

7.主线程根据EXE文件中的子系统值GUI/(CUI),执行WinMainCRTStartup/(MainCRTStartup)
a.得到一个新进程的全部命令行的指针。
b.得到一个新进程的环境变量指针。
c.通过STDLIB.H来初始化能被应用访问的C运行时全局变量。例
_osver, _winmajor, _winminor, _winver, _argc, _argv, _environ.
// Do runtime startup initializers.
_initterm( __xi_a, __xi_z );
d.执行EXE的全局或静态C++对象的构造函数(初始化)。
// Do C++ constructors (initializers) specific to this EXE
_initterm( __xc_a, __xc_z );
c.调用WinMain函数。
mainret = WinMain(
          GetModuleHandle(NULL), //EXE映象文件基地址
              NULL,
            lpszCommandLine,
              StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow: SW_SHOWDEFAULT
            );

8.至此,主线程启动工作完成,执行进入WinMain() 。在WinMain() 中执行MFC的消息循环,驱动主线程运行,直至消息循环终止。

--------------------------------
以下为退出过程

9.主线程继续WinMainCRTStartup() 执行exit(mainret)-> doexit()函数。执行一些清理工作。
a.除主线程外,锁其它线程。Makes sure only one thread is in the exit code at a time.
#ifdef _MT //多线程
_lockexit(); // assure only 1 thread in exit path
#endif
b.执行EXE中全局或静态C++对象的析构函数,在doexit() 中。例 MyApp::~MyApp()
c.对应于启动过程中通过STDLIB.H来初始化能被应用访问的C运行时全局变量,要执行清理工作
do pre-terminators,do terminators
d.调用ExitProcess(uExitCode)
终止除主线程之外的所有未结束的其它线程(包括在DLL中启动的线程)。由于调用ExitProcess() 而被强制终止的线程将造成内存泄漏。所以应在此之前的适当地方正确结束所有其它线程。
为每个DLL调用_DllMainCRTStartup() ,当所有DLL的DLLMain() 执行后,终止进程。

其中_DllMainCRTStartup(被ExitProcess()调用)中执行
a.调用你的DLL的DLLMain()函数,REASON为DLL_PROCESS_DETACH
b.调用_CRT_INIT() 函数 ,执行DLL中全局或静态C++对象的析构函数。例 MyDll::~MyDll()





本文转自
http://book.77169.org/ask32/how120191.htm
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值