IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 5.4 框架程序的状态信息 -> 正文阅读

[C++知识库]5.4 框架程序的状态信息

5.4.1 模块的概念

在线程中调用API函数的时候,代码到哪里去执行了呢?比如,在一条语句中调用了MessageBox函数,然后Windows就会弹出了一个对话框。可以肯定,在程序中并没有此函数的实现代码,而用于程序执行的代码最后又都会被链接成.EXE文件,所以最终的可执行文件中没有MessageBox函数的实现代码。这就说明,应用程序在启动的时候,不但加载了.EXE文件,还加载了包含API函数实现代码的文件。每一个被加载到内存中的文件称为一个模块。

一般进程是由多个模块组成的。通常应用程序都是通过模块句柄来访问进程中的模块。事实上,模块句柄的值就是该模块映射到进程中的地址。例如WinMain函数中的第一个参数hInstance,这就是主程序模块的句柄,即.EXE文件映射到内存后的地址。

使用ToolHelp函数可以很容易地查看一个进程都加载了哪些模块,例如下面的代码打印出了当前进程中模块的一些信息。
05ProcessModule

// ProcessModule.cpp文件
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
using namespace std;

void main()
{
	MODULEENTRY32 me32 = { 0 };
	
	// 在本进程中拍一个所有模块的快照
	HANDLE hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
	if(hModuleSnap == INVALID_HANDLE_VALUE)
		return;

	// 遍历快照中记录的模块
	me32.dwSize = sizeof(MODULEENTRY32);
	if(::Module32First(hModuleSnap, &me32))
	{
		do
		{
			cout << me32.szExePath << "\n";
			cout << "	模块在本进程中的地址:" << me32.hModule << "\n";
		}
		while(::Module32Next(hModuleSnap, &me32));
	}
	::CloseHandle(hModuleSnap);
}

首先,用CreateToolhelp32Snapshot函数给当前进程拍一个快照,TH32CS_SNAPMODULE参数指定了快照的类型,第二个参数指定了目标进程的ID号。然后用Module32First和Module32Next函数遍历快照中记录的模块信息,运行结果如图5.8所示。
在这里插入图片描述
这说明05ProcessModule进程是由3个模块组成的:05ProcessModule.exe(主程序模块)、ntdll.dll和kernel32.dll。这些模块都有一些不同于其他模块的属性,如模块的镜像文件在磁盘的位置,此模块中所有类的列表等,所以有必要定义一个数据结构来维护程序中模块的状态。

5.4.2 模块、线程的状态

模块状态记录了一些模块私有的数据,可以用AFX_MODULE_STATE类来描述它。

// _AFX_THREAD_STATE (线程状态)
class CWnd;
class _AFX_THREAD_STATE : public CNoTrackObject
{
public:
	AFX_MODULE_STATE* m_pModuleState;

	// 注册窗口类时使用(缓冲区)
	TCHAR m_szTempClassName[96]; 

	// 创建窗口时使用
	CWnd* m_pWndInit;		// 正在初始化的CWnd对象的指针
	HHOOK m_hHookOldCbtFilter;	// 钩子句柄

	MSG m_lastSendMsg;
};

EXTERN_THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState);
_AFX_THREAD_STATE* AfxGetThreadState();

同样,每创建一个线程就创建一个新的_AFX_THREAD_STATE对象,并用CThreadLocal类模板保存这个线程状态对象的指针。

_AFX_THREAD_STATE* AfxGetThreadState()
{
	return _afxThreadState.GetData();
}
THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState);

m_pModuleState成员保存了线程的模块状态,所以取得模块状态的代码如下。

AFX_MODULE_STATE _afxBaseModuleState;
AFX_MODULE_STATE* AfxGetAppModuleState()
{
	return &_afxBaseModuleState;
}

AFX_MODULE_STATE* AfxGetModuleState()
{
	_AFX_THREAD_STATE* pState = _afxThreadState.GetData();
	AFX_MODULE_STATE* pResult;
	if(pState->m_pModuleState != NULL)
		pResult = pState->m_pModuleState;
	else
		pResult = AfxGetAppModuleState();

	ASSERT(pResult != NULL);
	return pResult;
}

可以认为_afxBaseModuleState是进程模块状态的指针,是进程私有变量。这样一来,应用程序可以设置自己的模块状态,也可以使用这个全局的模块状态。由于现在所讨论的程序都是基于单模块的,所以一般都直接使用_afxBaseModuleState来保存模块信息。

在3.4节定义了模块线程状态AFX_MODULE_THREAD_STATE,在此除了要向里面增加新的成员以外,还要对函数AfxGetModuleThreadState进行重新定义。

class CWinThread;
class CHandleMap;
class AFX_MODULE_THREAD_STATE : public CNoTrackObject
{
public:
	// 指向当前线程对象(CWinThread对象)的指针
	CWinThread* m_pCurrentWinThread;

	// 窗口句柄映射
	CHandleMap* m_pmapHWND;
};

AFX_MODULE_THREAD_STATE* AfxGetModuleThreadState();

句柄映射是模块和线程局部有效的,属于模块-线程状态的一部分。取得模块-线程状态指针的函数应修改如下。

AFX_MODULE_THREAD_STATE* AfxGetModuleThreadState() 
{ 
    return AfxGetModuleState()->m_thread.GetData();
} 
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:32:27  更:2022-07-03 10:35:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:57:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码