设为首页  
联系我们  
加入收藏  
网页制作 冲浪宝典 图形图像 操作系统 软件教学 编程开发 认证考试 安全技术 站长专区 文学驿站 娱乐天地 游戏天地 办公软件
文章搜索
您的位置: 首页 >> 文章首页 >> 编程开发 >> 其他开发语言 >> Modules, Processes, Threads
精品推荐
其他开发语言点击TOP10
·数字小键盘指法练习
·用C语言编通讯录程序(初学者级别的)
·Modem 常用AT指令集
·单片机模拟I2C总线及24C02(I2C EEPROM)读写实例(源代码)
·C++经典电子书下载
·Thinking in C++ 简体中文第二版
·debug和release的区别
·error LNK2001: unresolved external symbol __ftol2 错误解决
·C库函数手册
·一个简单的C语言编译器
编程开发点击TOP10
·数字小键盘指法练习
·ASP.NET 程序中常用的三十三种代码
·用C语言编通讯录程序(初学者级别的)
·我写的Java学生成绩管理系统源代码
·CHK文件恢复工具
·Modem 常用AT指令集
·java笔试题
·异常java.sql.SQLException: Io exception:The Network Adapter could not establish connection
·单片机模拟I2C总线及24C02(I2C EEPROM)读写实例(源代码)
·C++经典电子书下载
精选专题

Modules, Processes, Threads

作者: 来源:网络文章 时间:2005-12-17 18:48:16

Modules, Processes, Threads(3) WIN32WLK 原始码中的 MODULE32.H 内含一个 MODREF 结构定义。每一个MODREF 有以下字段:

l         00h PMODREF pNextModRef

这个指针指向串行中的下一个 MODREF 结构。串行最后以 NULL 收尾。只要从行程的 process database 中取得 MODREFs 串行的头,然后一一追踪下去,就可以把行程所用到的每一个模块找出来。WIN32WLK 之中就有这样的示范。

l         10h WORD mteIndex

一个以 0 为基准的值,代表 pModuleTableArray 数组的索引。

l         18h PVOID ppdb

这是一个 PPROCESS_DATABASE,也就是一个指向 PROCESS_DATABASE 结构的指标,它提供一个从 MODREF 回头联结至「拥有此一 MODREF 之行程」的数据。稍后我会探讨 PROCESS_DATABASE

由于 Windows 95 必须看起来像是每一个行程有自己的一个模块串行,所以和模块有关的 API 函式如 GetModuleHandle 不能够在全域模块表格(pModuleTableArray)上动作,它们只能够在自己的 MODREF 串行上动作,然后再藉由获得的索引参考到全域模块表格的元素项目。例如,GetProcAddress 只能够寻找陈列于current MODREF 串行中的模组。即使这个模块已经被其它行程加载,GetProcAddress 还是无法找到它 -- 除非现行(current)行程也载入了它。

KERNEL32 物件

K32 对象是关键性的系统数据结构,放在 KERNEL32 heap 之中。有各式各样的K32 对象,统统都以相同的表头开始。决定它是否为一个 K32 对象的方法就是询问一个问题:应用程序之中可有 handles 代表此一对象?例如,应用程序可以拥有 file handles event handles,所以 file event 都是K32 对象。我不曾看过任何应用程序代码拥有MODREF IMTE handles,所以它们并不是 K32 对象。

每一个 K32 对象都以一个共通的表头开始。此表头拥有以下字段:

l         00h DWORD

对象型态。此值决定后续的结构成员如何解释。

l         04h DWORD

这是对象的参用次数(reference count),代表对象被使用的次数。例如,当你呼叫GetFileInformationByHandle,被询问的档案对象的参用次数就会累加 1;而在函式回返之前,参用次数又会减 1

现在,你或许渴望知道有哪些 K32 对象型态。以下就是一份清单:

K32OBJ_SEMAPHORE(0x1)

K32OBJ_event(0x2)

K32OBJ_mutex(0x3)

K32OBJ_CRITICAL_SECTION(0x4)

K32OBJ_PROCESS(0x5)

K32OBJ_THREAD(0x6)

K32OBJ_FILE(0x7)

K32OBJ_CHANGE(0x8; 请看 FindFirstChangeNotification

K32OBJ_CONSOLE(0x9)

K32OBJ_SCREEN_BUFFER(0xA)

K32OBJ_MEM_MAPPED_FILE(0xB;请看 CreateFileMapping

K32OBJ_SERIAL(0xC)

K32OBJ_DEVICE_IOCTL(0xD;请看 DeviceIoControl

K32OBJ_PIPE(0xE)

K32OBJ_MAILSLOT(0xF)

K32OBJ_TOOLHELP_SNAPSHOT(x10;请看 CreateToolhelp32Snapshot

K32OBJ_SOCKET(0x11)

本章剩余部份,我们主要的焦点放在行程对象和执行绪对象(IDs 5 6)。一个 processdatabase 其实就是一个 K32_PROCESS 对象,而一个 thread database 其实就是一个K32_THREAD 对象。就像你在「什么是 process handle?什么是 process ID?」一节即将看到的,一个 process handle table 其实就是一个指针数组,每一个指针指向各式各样的 K32 对象。

Windows 95 行程(Processes

行程其实就是一大堆对象的拥有权的集合。也就是说,行程拥有对象。行程可以拥有内存(更精确说是拥有 memory context),可以拥有 file handle,可以拥有执行绪,可以拥有一串行的 DLL 模块(被加载于此一行程的地址空间中)。

注意,行程并不代表「执行事实」(执行绪才是)。行程也不是 EXE 檔。在被载入之前,一个 EXE 档案只不过是一个程序。只有在被加载之后,Windows 95 才为它产生一个行程。一旦 Windows 95 产生一个行程,它也产生一个 memory context,容纳行程的执行绪在其中执行。此外,Windows 95 也产生出第一个执行绪,用来执行行程本身。如有必要,行程可以再产生执行绪。系统还会产生一个 file handle table,行程可以在其中持有一些开启的档案。最后,也是最重要的,Windows 95 产生一个 process database,用以表现这个行程。

Process database 是一种 K32 对象,内含与行程有关的大量信息。稍后我们将在「Windows95 Process DatabasePDB)」一节中详细观察其字段。Process database 所使用的内存来自 KERNEL32 heap,因此所有的process database 都可以被其它行程看到。

Process database 含有一系列的执行绪、一系列的被加载模块、预设之process heap handle、指向 process handle table 的指标、以及指向 memory context 的指标。此外还有更多更多的东西。

什么是process handle?什么是process ID

Process handle 基本上和 file handle 一样。它是一个不被明了的数值,你不能够说它是任何东西的指标。系统内部事实上是把 K32 对象的 handle 当作 process handle table 的索引。而从该数组中获得的,才是一个 K32 对象指针。然而,由于应用程序不需要直接处理 handle table,所以 process handle 是没有用的。

记住,因为每一个应用程序有它自己的 handle table,所以不同的行程在各自的地址空间中拥有相同的 process handle 是绝对可能的。例如,正常而言每一个行程都有一个 process handle 为它而开,其值总是 1。也就是说,process handle 并不是可以赖以判别行程的资料。另一个例子是:如果程序为自己这个行程打开另一个 process handle,那么就有两个handles,对应至同一个行程。

一个 process handle 就像一个 file handle。在其行程之外别无意义。至于一个 process ID,则是在各行程之间独一无二不会冲突的数值,它是一个指标,指向process database 结构,甚至虽然微软在其中加了点料。WIN32WLK 示范神奇的转换公式,把 process ID 转换为一个有用的指标。

Windows 95 Process DatabasePDB

Windows 95 的每一个 process database 都是一块从 KERNEL32 heap 配置而来的记忆体。KERNEL32 通常以 PDB 缩写字取代又臭又长的 "process database"。每一个 PDB 就是一个「第一字组为 5K32OBJ_PROCESS)」的K32 物件。WIN32WLK 程序的PROCDB.H 中有一个 PDB C 语言定义,我们把每一个字段看清楚些:

l         00h DWORD Type

此值必为 5K32OBJ_PROCESS

l         04h DWORD cReference

参用次数(reference count)。也就是此一 PDB 被使用的次数。

l         08h DWORD un1

此字段之真实意义未知。似乎总是 0

l         0Ch DWORD someEvent

这是一个指向 K32OBJ_EVENT 对象的指针。Event 对象用于WaitForSingleObject 这样的函式。

l         10h DWORD TerminationStatus

当你呼叫 GetExitCodeProcess,传回的就是这个值。所谓退出代码(exit code)就是 mainWinMain 的回返值。它也可以被 ExitProcess TerminateProcess 指定。当一个行程还在执行时,此字段为 0x103STILL_ACTIVE)。

l         14h DWORD un2

此字段之真实意义未知。似乎总是 0

l         18h DWORD DefaultHeap

Default process heap 的地址。GetProcessHeap 传回的就是这个值。

l         1Ch DWORD MemoryContext

一个指标,指向行程的 memory context。所谓 memory context,内含 page directorymapping,用以提供行程在 4GB 地址空间中的私人区域。第5章对于 memory context 有更多描述。

l         20h DWORD flags

这个旗标值的意义如下

fDebugSingle 0x00000001 如果设立表示行程正被除错中

fCreateProcessEvent 0x00000002 设立于除错行程中在起始之后

fExitProcessEvent 0x00000004 可以在除错行程中在结束时候被设立

fWin16Process 0x00000008 表示一个 16 位程序

fDosProcess 0x00000010 表示一个 DOS 程序

fConsoleProcess 0x00000020 表示一个 console文字模式Win32 程序

fFileApisAreOem 0x00000040 请看 API 文件中的 SetFileApisToOEM 说明

fNukeProcess 0x00000080

fServiceProcess 0x00000100 例如 MSGSRV32.EXE

fLoginScriptHack 0x00000800 可能是一个 Novell 网络签入行程

fSendDllNotifications 0x00200000

fDebugEventPending 0x00400000 例如,在除错器中被停下来

fNearlyTerminating 0x00800000

fFaulted 0x08000000

fTerminating 0x10000000

fTerminated 0x20000000

fInitError 0x40000000

fSignaled 0x80000000

l         24h DWORD pPSP

这个值是此一行程之 DOS PSP 的线性地址。Win16 Win32 程序都会设定此字段。此一线性地址总是在 1MB(真实模式 DOS 码所能看到的最高地址)之下。请参考28h 栏位。

l         28h WORD PSPSelector

这是一个 selector,指向此一行程之 DOS PSPWin16 Win32 程序都有 DOS PSP。请参考 24h 字段。

l         2Ah WORD MTEIndex

这里内含一个全域模块表格(pModuleTableArray)的索引值。经由此索引值而取出之 IMTE正是此一行程对应的IMTEIMTE pModuleTableArray 已于本章先前讨论过。

l         2Ch WORD cThreads

此字段记录此一行程拥有的执行绪个数。

l         2Eh WORD cNotTermThreads

此字段记录属于行程所有而尚未结束之执行绪个数。它怎么看都应该和上一字段相同。

l         30h WORD un3

此字段之真实意义未知。似乎总是 0

l         32h WORD cRing0Threads

此字段记录由VMM32.VXD 管理的ring0 执行绪个数。对于一般程序而言,其值应该与cThreads 字段值相同。然而在KERNEL32.DLL 之中,此值比cThreads 字段值多1

l         34h HANDLE HeapHandle

此字段是一个 HEAP handle,此 HEAP 内含属于这个行程的表格(或可能其它东西)。这里记录的总是 KERNEL32 shared heap handle

l         38h HTASK W16TDB

这是一个 selector,指向行程相关的 Win16 Task DatabaseTDB)。Win16 Win32 程序都有 TDB selector,并且维护一个合法的 TDB

l         3Ch DWORD MemMapFiles

一个指标,指向「此一行程所使用之内存映像文件所组成的串行」中的第一个节点。每一个内存映像文件都出现为串行中的一个节点。节点的格式是:

DWORD 内存映像文件的基地址

DWORD 指向下一个节点;或是 0

l         40h PENVIRONMENT_DATABASE pEDB

一个指标,指向 environment databaseEnvironment database 中内含目前的子目录、环境变量、行程命令列、标准 handles(例如 stdin)、以及其它项目。我将在「EnvironmentDatabase」一节中描述其详细格式。

l         44h PHANDLE_TABLE pHandleTable

这是一个指标,指向 process handle table。所有的 handles 都在这里面,包括file handlesevent handlesprocess handles 等等等。在 DOS/Win16 环境中的对等物品是 DOS System File TableSFT)。关于 SFT 请参考Schulman 等人所著的 Undocumented DOS,第二版。然而毕竟有所不同。SFT 适用于整个系统,Win32 process handle table 则只适用于一个行程

l         48h strUCt _PROCESS_DATABASE * ParentPDB

这是一个指标,指向父行程的 PROCESS_DATABASE。对一般程序而言父行程是Windows95 的档案总管(EXPlorer)。MSGSRV32 则又是 Explorer initial "service" processes 的父行程。

l         4Ch PMODREF MODREFlist

这个字段指向行程的模块串行的起头。这也就是稍早描述过的 MODREFs 串行。

l         50h DWORD ThreadList

一个指标,指向此一行程所拥有的执行绪的串行。目前我还不知道这个串行的真正格式。

l         54h DWORD DebuggeeCB

这是一个被除错程序的 context。当一个行程被除错,这个字段即指向 2GB 以上的一个区域,该区域包含一个指针,指向被除错者的 process database

l         58h DWORD LocalHeapFreeHead

这个指标指向「此一行程预设之 heap」的自由区块串行起头。第5章对于其格式有详细的描述。

l         5Ch DWORD InitialRing0ID

此字段意义未知。似乎总是为 0

l         60h CRITICAL_SECTION crst

这个字段是一个 CRITICAL_SECTION,被各式各样的 API 用来同步控制同一行程中的各执行绪。稍后在许多伪码之中你会看到这个 critical section 的作用。

l         78h DWORD un4[3]

这三个 DWORD 之真实意义未知。似乎总是 0

l         84h DWORD pConsole

如果这个行程使用 console(也就是说它是一个文字模式程序),此一字段即指向一个用于输出的 console 对象(K32OBJ_CONSOLE