现在的位置: 首页 > 综合 > 正文

Windows 95 System Programming SECRENTS学习笔记—第三章(5)

2012年09月25日 ⁄ 综合 ⁄ 共 3487字 ⁄ 字号 评论关闭

补充:

    进程的handle保存在自己的process handle table中,系统可以通过hProcess找到对应的process database,那么进程所拥有的线程的handle保存在哪儿?前面提到过,在PDB中有两个位置与此有关:一个用来保存该进程拥有的线程个数,另一个保存ThreadList的表头。个人感觉,hTread应该在process handle table中,因为可以对hThread是用CloseHandle,而且线程也是K32对象。

 

Thread Database

Thread Database是一个K32对象(K32OBJ_THREAD),从KERNEL32共享数据区种分配而来。在本章的示例代码的ThreadDB.h文件中,有关于Thread DatabaseC语言定义,其格式如下:

00h DWORD Type

此位置为6,表示K32OBJ_THREAD对象(在Windows 2000 or later中是否还如此,未知)

 

04h DWORD cReference

此位置内含线程的引用计数

 

08h PROCESS_DATABASE pProcess

这是一个指针,指向线程所属的进程

 

0Ch DWORD someEvent

一个指针,指向K32OBJ_EVENT对象。Event对象通常被交给WaitForSingleObject。这个Event对象正是你调用WaitForSingleObject函数时给予的Event

 

10h DWORD pvExcept

这是一个指针,指向结构化异常处理的串链头(结构化异常处理将会在稍后讨论)。请注意,这个位置也标识了Task Database中的TIBThread Information Block)巢状结构的起始处。TIB将在稍后讨论。

补充:

   似乎本书中关于TIB结构的描述,在Windows 2000SP4)中仍然有效,在对本章的学习结束后,我会将原书中本章的例程移植到Windows 2000下。目前估计可能无法完全移植,因为我没有Windows 2000下的Kernel32.Lib的完全版。希望在完成《Undocumented Windows 2000 Secrets》一书的学习后,我能补齐这些内容。2004-12-26

 

14h DWORD TopOfStack

此位置存放的是线程堆栈的最高地址。一般而言,保留给线程的堆栈大小是1MB

补充:Windows 2000中线程的默认堆栈大小也是1MB

 

18h DWORD StackLow

此位置存放的是线程堆栈的最低位标记(以page为单位)。把TopOfStack减去StackLow就可以知道线程目前使用了多大的堆栈。

 

1Ch WORD W16TDB

这里存放的是Win 16 task databaseselector

 

1Eh WORD StackSelector16

Win32代码下移(thunk down)至16位代码之前,必须先切换到一个16位堆栈上。这个成员存放的就是该16位堆栈的selector

 

20h DWORD SelmanList

一个指针,指向线程的SelmanList。“Selman”的含义是“Selector Manager”。KERNEL32中的Selman似乎有责任管理selectors,线程可以从中配置、作为给种用途。

 

24h DWORD UserPointer

此位置的精确意义还不明确。然而TIB结构的文件中说,这个位置可以给应用程序使用。别忘了,TIB结构在Thread Database中是巢状的。

 

28h  PTIB  pTIB

这个位置指向TIBThread Information Block)。Windows 95TIB位于Thread Database之中,所以此指针其实是指向Thread Database的另一个位置:pvExcept位置(偏移地址10h)。

 

Thread Information BlockTIB

Thread Database中,有一些成员对于执行中的程序极为有用。事实上,它们是如此的有用,以至于Win32架构让它们可以立刻被取用,而不需要经过Thread Database。这些成员被放置在一个名为Thread Information BlockTIB)的结构中。Thread Database10h-3Ch成员统统被放置在TIB之中。

 

应用程序如何取得TIB呢?如果你看过Win32程序的汇编代码,你会发现FS寄存器的使用频率非常高(Windows 2000 or later是否如此,目前还未知。2004-12-27)。等一下,Win32不是会移动节区吗?显然答案是Yes,但是Win32底层(包括Windows NT)都使用FS寄存器,用以指向当前正在执行的线程的TIB.Win32并不是第一个这么做的操作系统,OS/2 2.0就已经如此了。就像你所感受到的,是的,当Windows 95切换线程时,调度器必须更改FS寄存器的值,让其包含一个selector,指向新的TIB

 

FS寄存器和TIB的主要用途就是增加结构化异常处理链(structured exception handing chain)的项目个数。处理链的头部存放在TIB0偏移处,所以当你看到汇编代码使用FS:[0],你就知道它正在做某些与结构化异常有关的动作了。

 

TIB的另两个成员也被十分广泛的使用,它们是pvQueuepvTLSArray(分别是28h2Ch成员)。pvQueue成员存放的是当前线程的消息队列的handle,此成员常常被USER.EXE的窗口系统使用。因为在Windows 95之中,焦点窗口(focus windows)并非整个系统只有一个。pvTLSArray则指向Thread Database中的TLS数组。编译器厂商把它和可执行文件的.tIs section连用,提供透明化的所谓“per-thread global variable”。

 

虽然TIB结构的布局可以从Thread Database中推算出来,我要在这里提供一点摘要。本章的示例代码中的TIB.H中有TIBC语言描述。微软对此的第一份文档是Windows NT 3.5 DDK提供的NTDDK.H

 

Windows 95TIB内容如下:

00h  DWORD  pvExcept

04h  DWORD  TopOfStack

08h  DWORD  StackLow

0Ch  WORD   W16TDB

0Eh  WORD   StackSelector16

10h  DWORD  SelmanList

14h  DWORD  UserPointer

18h  PTIB     pTIB

1Ch  WORD   TIBFlags

1Eh  WORD   Win16MutexCount

20h  DWORD  DebugContext

24h  PDWORD pCurrentPriority

28h  DWORD  MessageQueue

2Ch  DWORD  pTLSArray

 

如果想知道每个成员的意义,把其偏移值增加10h,然后看看上一节的结构内容,就可以知道了。请注意,其中只有一些成员对于其他Win32平台是共同的。

 

补充:

    Windows NT/2000系统中,线程信息块(Thread Information Block)被定义为NT_TIB结构,在Windows NT/2000 DDKNTDDK.H中,可以找到该结构的C语言定义。其布局如下:

//

//  NT_TIB - Thread Information Block - Portable part.

//

//      This is the subsystem portable part of the Thread Information Block.

//      It appears as the first part of the TEB for all threads which have

//      a user mode component.

//

//      From Windows 2000 DDK 1999-9-11

 

// begin_winnt

 

typedef struct _NT_TIB {

    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;  // SEH链入口

    PVOID StackBase;  // 堆栈基址

    PVOID StackLimit;  // 堆栈大小

    PVOID SubSystemTib;

    union {

        PVOID FiberData;

        ULONG Version;

    };

抱歉!评论已关闭.