windows 进程
文章内容引自《Windows核心编程》
windows进程创建
CreateProcess函数
系统创建一个进程内核对象,初始引用计数为1。进程内核对象不是进程本身,系统为新进程创建一个虚拟地址空间,将可执行文件(和所有必要dll)的代码及数据加载到进程的地址空间。
然后,系统为新进程的主线程创建一个线程内核对象(引用计数为1),操作系统用它来管理这个线程。
主线程一开始就会执行c/c++运行时的启动例程,它是由链接器设为应用程序入口的,最终会调用应用程序WinMain,WWinMain,main或者wmain函数。
CreateProcess在进程完全初始化前就返回True,有可能dll找不到或者不能正确初始化,进程就会终止。因为CreateProcess返回True,所以父进程不会注意到任何初始化问题。
进程终止
四种方式终止进程
- 主线程的入口点函数返回(推荐)
- 进程中的一个线程调用ExitProcess函数(避免)
- 另一个进程中的线程调用TerminateProcess函数(避免)
- 进程中的所有线程都“自然消亡”(几乎不可能)
在推荐的方式1中,会保证以下操作会被执行
- 该线程创建的任何C++对象都将由这些对象的析构函数正确销毁;
- 操作系统将正确释放线程栈使用的内容;
- 系统将进程的退出代码(在进程内核对象中维护)设为入口点函数的返回值;
- 系统递减进程内核对象的使用技术。
当主线程的入口点函数返回时,会返回到c/c++运行库启动代码,启动代码将正确清理进程使用的全部C运行时资源。释放了C运行时资源之后,C运行时启动代码将显示调用ExitProcess,于此同时,运行中的其他任何线程都会随进程一起终止。
windows sdk文档说,一个进程在其所有线程都终止后才会终止。不过,c/c++运行库为应用程序采用了一个不同的策略:不管进程中是否还有其他线程在运行,只要应用程序的主线程从它的入口点函数返回,C/C++运行库就会调用ExitProcess来终止进程。
但是如果调用的不适ExitProcess,而是ExitThread或者入口点函数直接返回,那么应用程序的主线程将停止执行,但是只要进程中仍有其他线程正在运行,进程就不会终止。
当线程终止运行时
操作系统会执行以下操作
- 终止进程中遗留的任何线程;
- 释放进程分配的所有用户对象和GDI对象,关闭所有内核对象;
- 进程的退出代码从STILL_ACTIVE变为传给ExitProcess或TerminateProcess函数的代码;
- 进程内核对象的状态变成已触发状态
- 进程内核对象的引用计数-1
子进程
为了在处理工作期间保护地址空间,一个办法是让一个新进程来执行工作。然后,既可以在新进程终止之后,才继续我们自己的工作,也可以在新进程运行期间继续自己的工作。
子进程会操作到父进程地址空间中的数据,在这种情况下,最好让进程它自己的地址空间中运行,并只允许它访问父进程地址空间中与它的工作有关的数据。
这涉及到进程间通信,包括动态数据交换(Dynamic Data Exchange, DDE),OLE,管道,邮件槽等;共享数据最方便的方式之一就是内存映射文件。