进程
1.什么是进程?
进程被定义为一个正在运行的程序的实例,它由两个部分组成:
1)操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。
2)地址空间。它包含所有可执行模块或DLL模块的代码和数据。它还包含动态内存分配的空间。如线程堆栈和堆分配空间。
Q:什么是DDL模块?
A:DLL 是一个包含可由多个程序同时使用的代码和数据的库。例如,在Windows 操作系统中,Comdlg32 DLL 执行与对话框有关的常见函数。因此,每个程序都可以使用该 DLL 中包含的功能来实现“打开”对话框。这有助于促进代码重用和内存的有效使用。
通过使用 DLL,程序可以实现模块化,由相对独立的组件组成。例如,一个计帐程序可以按模块来销售。可以在运行时将各个模块加载到主程序中(如果安装了相应模块)。因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。
此外,可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,您可能具有一个工资计算程序,而税率每年都会更改。当这些更改被隔离到 DLL 中以后,您无需重新生成或安装整个程序就可以应用更新。
2.进程与线程的关系
1)单个进程至少包含一个线程,即系统自动为该进程创建的第一个线程,称为主线程,该线程负责执行包含在进程的地址空间中的代码。
2)每个线程都有它自己的一组CPU寄存器和它自己的堆栈,这些线程都“同时”执行进程地址空间中的代码。(操作系统通过循环方式为线程提供时间片,从而造成一种所有线程都是同时运行的假象)。
3)进程可以创建其他进程,线程也可以创建其他线程。
编写第一个Windows应用程序
1.Windows支持的应用程序类型
1)基于图形用户界面(GUI)的应用程序
有个图形前端程序,能创建窗口,拥有菜单,可以通过对话框与用户打交道,并可使用所有的标准“Windows”组件。Windows配备的所有应用程序附件几乎都是基于GUI的应该程序。
链接程序开关是/SUBSYSTEM:WINDOWS
2)基于控制台用户界面(CUI)的应用程序
CUI应用程序属于文本操作的应用程序,通常不能用于创建窗口或处理消息,并且它们不需要图形用户界面。命令外壳程序CMD.EXE(用于Windows 2000)和COMMAND.COM(用于Windows 98)都是典型的基于CUI的应用程序。
链接开关是/SUBSYSTEM:CONSOLE
(当用户运行一个应用程序时,操作系统的加载程序就会查看可执行图形程序的标题,并抓取该子系统的值。如果该值指明一个CUI应用程序,那么加载程序就会自动保证为该应用程序创建文本控制台窗口)
3)两种类型的应用程序界限模糊
可以创建用于显示对话框的CUI应用程序:命令外壳程序可能拥有一个特殊的命令,使它能够显示一个图形对话框,在这个对话框中,可以选定你要执行的命令,而不必记住该外壳程序支持的各个不同的命令。
也可以建立控制台窗口的GUI应用程序,在这个窗口中,我可以查看应用程序执行时的调试信息。
2.Windows应用程序使用的进入点函数
Windows应用程序必须拥有一个在应用程序启动运行时调用的进入点函数。但实际上操作系统调用的不是进入点函数,而是C/C++运行期启动函数(负责对C/C++运行期库进行初始化)。
![](https://img.haomeiwen.com/i12517966/4e83c3a83a1ee66b.png)
·需要ANSI字符和字符串的GUI应用程序
![](https://img.haomeiwen.com/i12517966/60702c64c4196ba5.png)
·需要UNICODE字符和字符串的GUI应用程序
![](https://img.haomeiwen.com/i12517966/bc058e9db9701d45.png)
·需要ANSI字符和字符串的CUI应用程序
![](https://img.haomeiwen.com/i12517966/a4d062a9c87f6eb3.png)
·需要UNICODE字符和字符串的CUI应用程序
![](https://img.haomeiwen.com/i12517966/b40717eca6cfaf55.png)
3.链接程序与进入点函数
链接程序负责在它连接可执行文件时选择相应的C/C++运行期启动函数。
Q:什么是C/C++运行期启动函数?
A:可以在crtexe.c文件中找到4个启动函数【即WinMainCRTStartup、wWinMainCRTStartup、mainCRTStartup和wmainCRTStartup】的源代码。这些函数的用途简单总结如下:a)获取指向新进程的完整命令行的一个指针;获取指向新进程的环境变量的一个指针;b)初始化c/c++运行库的全局变量。如果包含了StdLib.h,我们的代码就可以访问这些变量;c)初始化c运行库内存分配函数(malloc和calloc)和其他底层I/O例程使用的堆(heap);d)调用所有全局和静态c++类对象的构造函数。
所有的C/C++运行期启动函数的作用基本上都是相同的。它们的差别在于,它们究竟是处理ANSI字符串还是UNICODE字符串,以及它们在对C运行期库进行初始化后它们调用哪个进入点函数。
如果设定了/SUBSYSTEM:WINDOWS链接程序开关,那么该链接程序期望找到一个WinMain或wWinMain函数。如果这两个函数都不存在,链接程序便返回一个“未转换的外部符号”的错误消息。否则,它可以分别选择WinMainCRTStartup函数或wWinMainCRTStartup函数。
同样,如果设定了/SUBSYSTEM:CONSOLE链接程序开关,那么该链接程序便期望找到main或wmain函数,并且可以分别选择mainCRTStartup或wmainCRTStartup函数。同样,如果main或wmain 都不存在,那么链接程序返回一条“未转换外部符号”的消息。
当删除/SUBSYSTEM链接程序开关后,链接程序自动确定应用程序应该链接到哪个子系统。当进行链接时,链接程序要查看代码中存在 4个函数(WinMain、wWinMain 、main或wmain)中的哪一个。然后确定可执行程序应该是哪一个子系统,并且确定可执行程序中应该嵌入哪个C/C++启动函数。
4.C运行期的exit函数
当进入点函数返回时,启动函数便调用 C运行期的exit函数,将返回值(nMainRetVal)传递给它。Exit函数负责下面的操作:
• 调用由_onexit函数的调用而注册的任何函数。
• 为所有全局的和静态的C + +类对象调用析构函数。
• 调用操作系统的ExitProcess函数,将nMainRetVal传递给它。这使得该操作系统能够撤消进程并设置它的exit代码
5.进程的实例句柄——加载到进程地址空间的每个可执行文件或DLL文件均被赋予一个独一无二的实例句柄。
1)LoadIcon函数
对于加载资源的函数调用来说,通常都需要实例句柄的值。若要从可执行文件的映象来加载图标资源,需要调用下面这个函数:
![](https://img.haomeiwen.com/i12517966/e9ec7c16e5f7fabe.png)
hinst实例句柄,指明哪个文件(可执行文件或DLL文件)包含想要加载的资源
pszIcon加载图标资源名字
2)GetModuleFileName函数
有些函数需要HMODULE类型参数,实际上HMODULE与HINSTANCE是完全相同的对象。
PS:之所以存在两个数据类型,原因是在16位Windows中,HMODULE和HINSTANCE用于标识不同的东西。
网友评论