Win32 系统线程信息块(TIB)浅析
2009-03-05 20:02:37 来源:WEB开发网此处关键是 Win32 编译器暗中知道 TIB 的信息并产生访问它的代码。因为编译器无法知道代码运行在哪个 Win32 系统上,你可以安全地假设任何引用 FS 段的编译器产生的代码使用的都是 TIB 在 Win32 平台上的公用域。
TIB 中的公用域
你刚看了一个 TIB 结构的例子,其中就有在所有 Win32 平台上公用域。在这一部分,我会列出所有的公用域以及简短说明。至于在Win32 平台之间有差别的那些域以后来讲。
定义 TIB 结构域的头文件零零散散有几个。不幸的是,这些文件对 TIB 的定义相互并不一致和完整。在 Windows NT DDK 中,你会发现 NTDDK.H 中定义为 NT_TIB 结构。在 Windows NT 3.51 的补丁包 SP3 更新文件中,新的 WINNT.H 文件也定义了一个 NT_TIB 结构。此外,Windows 95 的开发人员在线发布的.H 文件内容中是 TIB。在我的描述中,我尝试使用广泛认可的名称。你会在 TIB.H 文件中看到这些名称,这个文件将随本文例子程序 SHOWTIB 一起提供:
TIB.H
//===========================================================
// File: TIB.H
// Author: Matt Pietrek
// From: Microsoft Systems Journal "Under the Hood", May 1996
//===========================================================
#pragma pack(1)
typedef struct _EXCEPTION_REGISTRATION_RECORD
{
struct _EXCEPTION_REGISTRATION_RECORD * pNext;
FARPROC pfnHandler;
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
typedef struct _TIB
{
PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list
PVOID pvStackUserTop; // 04h Top of user stack
PVOID pvStackUserBase; // 08h Base of user stack
union // 0Ch (NT/Win95 differences)
{
struct // Win95 fields
{
WORD pvTDB; // 0Ch TDB
WORD pvThunkSS; // 0Eh SS selector used for thunking to 16 bits
DWORD unknown1; // 10h
} WIN95;
struct // WinNT fields
{
PVOID SubSystemTib; // 0Ch
ULONG FiberData; // 10h
} WINNT;
} TIB_UNION1;
PVOID pvArbitrary; // 14h Available for application use
struct _tib *ptibSelf; // 18h Linear address of TIB structure
union // 1Ch (NT/Win95 differences)
{
struct // Win95 fields
{
WORD TIBFlags; // 1Ch
WORD Win16MutexCount; // 1Eh
DWORD DebugContext; // 20h
DWORD pCurrentPriority; // 24h
DWORD pvQueue; // 28h Message Queue selector
} WIN95;
struct // WinNT fields
{
DWORD unknown1; // 1Ch
DWORD processID; // 20h
DWORD threadID; // 24h
DWORD unknown2; // 28h
} WINNT;
} TIB_UNION2;
PVOID* pvTLSArray; // 2Ch Thread Local Storage array
union // 30h (NT/Win95 differences)
{
struct // Win95 fields
{
PVOID* pProcess; // 30h Pointer to owning process database
} WIN95;
} TIB_UNION3;
} TIB, *PTIB;
#pragma pack()
SHOWTIB.CPP
//==========================================================================
// File: SHOWTIB.CPP
// Author: Matt Pietrek
// To Build:
// CL /MT SHOWTIB.CPP USER32.LIB (Visual C++)
// BCC32 -tWM SHOWTIB.CPP (Borland C++, TASM32 required)
//==========================================================================
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#pragma hdrstop
#include "tib.h"
#define SHOWTIB_MAX_THREADS 64
CRITICAL_SECTION gDisplayTIB_CritSect;
void DisplayTIB( PSTR pszThreadName )
{
PTIB pTIB;
WORD fsSel;
EnterCriticalSection( &gDisplayTIB_CritSect );
__asm
{
mov EAX, FS:[18h]
mov [pTIB], EAX
mov [fsSel], FS
}
printf( "Contents of thread %sn", pszThreadName );
printf( " TIB %04X (Address: %08X)n", fsSel, pTIB );
printf( " SEH chain: %08Xn", pTIB->pvExcept );
printf( " Stack top: %08Xn", pTIB->pvStackUserTop );
printf( " Stack base: %08Xn", pTIB->pvStackUserBase );
printf( " pvArbitray: %08Xn", pTIB->pvArbitrary );
printf( " TLS array *: %08Xn", pTIB->pvTLSArray );
printf( " ----OS Specific fields----n" );
if ( 0xC0000000 == (GetVersion() & 0xC0000000) ) // Is this Win95 ?
{
printf( " TDB: %04Xn", pTIB->TIB_UNION1.WIN95.pvTDB );
printf( " Thunk SS: %04Xn", pTIB->TIB_UNION1.WIN95.pvThunkSS );
printf( " TIB flags: %04Xn", pTIB->TIB_UNION2.WIN95.TIBFlags );
printf( " Win16Mutex count: %04Xn", pTI->TIB_UNION2.WIN95.Win16MutexCount );
printf( " DebugContext: %08Xn", pTIB->TIB_UNION2.WIN95.DebugContext );
printf( " Current Priority *: %08X (%u)n",
pTIB->TIB_UNION2.WIN95.pCurrentPriority,
*(PDWORD)(pTIB->TIB_UNION2.WIN95.pCurrentPriority) );
printf( " Queue: %04Xn", pTIB->TIB_UNION2.WIN95.pvQueue );
printf( " Process *: %08Xn", pTIB->TIB_UNION3.WIN95.pProcess );
}
else if ( 0 == (GetVersion() & 0xC0000000) ) // Is this WinNT ?
{
printf(" SubSystem TIB: %08Xn", pTIB->TIB_UNION1.WINNT.SubSystemTib);
printf(" FiberData: %08Xn", pTIB->TIB_UNION1.WINNT.FiberData );
printf(" unknown1: %08Xn", pTIB->TIB_UNION2.WINNT.unknown1);
printf(" process ID: %08Xn", pTIB->TIB_UNION2.WINNT.processID);
printf(" thread ID: %08Xn", pTIB->TIB_UNION2.WINNT.threadID);
printf(" unknown2: %08Xn", pTIB->TIB_UNION2.WINNT.unknown2);
}
else
{
printf(" Unsupported Win32 implementationn" );
}
printf( "n" );
LeaveCriticalSection( &gDisplayTIB_CritSect );
}
void MyThreadFunction( void * threadParam )
{
char szThreadName[128];
wsprintf( szThreadName, "%u", threadParam ); // Give the thread a name
// If multiple threads are specified, give'em different priorities
if ( (DWORD)threadParam & 1 )
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST );
DisplayTIB( szThreadName ); // Display the thread's TIB
// Let other threads execute while this thread is still alive. The idea
// here is to try and prevent memory region and selector reuse.
Sleep( 1000 );
}
int main( int argc, char *argv[] )
{
if ( argc < 2 )
{
printf( "Syntax: SHOWTIB [# of threads]n" );
return 1;
}
InitializeCriticalSection( &gDisplayTIB_CritSect );
unsigned cThreads = atoi( argv[1] );
if ( (cThreads < 1) || (cThreads > SHOWTIB_MAX_THREADS) )
{
printf( "thread count must be > 1 and < %un", SHOWTIB_MAX_THREADS );
}
else
{
// Allocate an array to hold the thread handles
HANDLE threadHandles[ SHOWTIB_MAX_THREADS ];
// Create the specified number of threads
for ( unsigned i = 0; i < cThreads; i++ )
threadHandles[i] = (HANDLE)
_beginthread(MyThreadFunction,0,(PVOID)i);
// Wait for all the threads to finish before we exit the program
WaitForMultipleObjects( cThreads, threadHandles, TRUE, INFINITE );
// We don't need the thread handles anymore. Close'em!
for ( i = 0; i < cThreads; i++ )
CloseHandle( threadHandles[i] );
}
DeleteCriticalSection( &gDisplayTIB_CritSect );
return 0;
}
更多精彩
赞助商链接