GetCurrentThread()返回的是一个伪句柄.
例如:
HANDLE hThread=NULL;
int WINAPI ThreadFun(void)
{
hThread = GetCurrentThread();
Sleep(1000 * 100);
}
void main()
{
//创建线程
...
//这下面这个句没有起到作用,因为是伪句柄.
// TerminateThread(hTread,3);
//WaitForSingObject(hThread,3);
}
以下为核心编程文章
6.8 对自己的ID概念应该有所了解
当线程运行时,它们常常想要调用Wi n d o w s函数来改变它们的运行环境。例如,线程可能想要改变它的优先级或它的进程的优先级(优先级将在第7章中介绍)。由于线程常常要改变它的(或它的进程的)环境,因此Wi n d o w s提供了一些函数,使线程能够很容易引用它的进程内核对象,或者引用它自己的线程内核对象:
HANDLE GetCurrentProcess(); HANDLE GetCurrentThread();
上面这两个函数都能返回调用线程的进程的伪句柄或线程内核对象的伪句柄。这些函数并不在创建进程的句柄表中创建新句柄。还有,调用这些函数对进程或线程内核对象的使用计数没有任何影响。如果调用C l o s e H a n d l e,将伪句柄作为参数来传递,那么C l o s e H a n d l e就会忽略该函数的调用并返回FA L S E。
当调用一个需要进程句柄或线程句柄的Wi n d o w s函数时,可以传递一个伪句柄,使该函数执行它对调用进程或线程的操作。例如,通过调用下面的G e t P r o c e s s Ti m e s函数,线程可以查询它的进程的时间使用情况:
FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime; GetProcessTimes(GetCurrentProcess(), &ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime);
同样,通过调用G e t T h r e a d Ti m e s函数,线程可以查询它自己的线程时间:
FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime; GetThreadTimes(GetCurrentThread(), &ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime);
少数Wi n d o w s函数允许用进程或线程在系统范围内独一无二的I D来标识某个进程或线程。下面这两个函数使得线程能够查询它的进程的唯一I D或它自己的唯一I D:
DWORD GetCurrentProcessId(); DWORD GetCurrentThreadId();
这两个函数通常不像能够返回伪句柄的函数那样有用,但是有的时候用起来还是很方便的。将伪句柄转换为实句柄
有时可能需要获得线程的实句柄而不是它的伪句柄。所谓“实句柄”,我是指用来明确标识一个独一无二的线程的句柄。请看下面的代码:
DWORD WINAPI ParentThread(PVOID pvParam)
{
HANDLE hThreadParent = GetCurrentThread();
CreateThread(NULL, 0 , ChildThread, (PVOID)hThreadParent, 0, NULL);
//Function continues...
}
DWORD WINAPI ChildThread(PVOID pvParam)
{
HANDLE hThreadParent = (HANDLE) pvParam;
FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime;
GetThreadTimes(hThreadParent, &ftCreationTime,
&ftExitTime, &ftKernelTime, &ftUserTime);
// Function continues...
}
你能发现这个代码段存在的问题吗?这个代码的目的是让父线程给子线程传递一个线程句柄,以标识父线程。但是,父线程传递了一个伪句柄,而不是一个实句柄。当子线程开始运行时,它将一个伪句柄传递给G e t T h r e a d Ti m e函数,使子线程得到它自己的C P U时间,而不是父线程的C P U时间。出现这种情况的原因是线程的伪句柄是当前线程的句柄,也就是说,它是调用函数的线程的句柄。
为了修改这个代码,必须将伪句柄变成实句柄。D u p l i c a t e H a n d l e函数能够执行这一转换:
BOOL DuplicateHandle( HANDLE hSourceProcess, HANDLE hSource, HANDLE hTargetProcess, PHANDLE phTarget, DWORD fdwAccess, BOOL bInheritHandle, DWORD fdwOptions);
通常可以使用这个函数,用与另一个进程相关的内核对象来创建一个与进程相关的新句柄。然而,可以用一种特殊的方法来使用这个函数,以便修改上面介绍的代码段。正确的代码段应该是下面的样子:
DWORD WINAPI ParentThread(PVOID pvParam) {
HANDLE hThreadParent;
DuplicateHandle(
GetCurrentProcess(), // Handle of process that thread
// pseudo-handle is relative to
GetCurrentThread(), // Parent thread's pseudo-handle
GetCurrentProcess(), // Handle of process that the new, real,
// thread handle is relative to
&hThreadParent, // Will receive the new, real, handle
// identifying the parent thread
0, // Ignored due to DUPLICATE_SAME_ACCESS
FALSE, // New thread handle is not inheritable
DUPLICATE_SAME_ACCESS); // New thread handle has same
// access as pseudo-handle
CreateThread(NULL, 0, ChildThread, (PVOID) hThreadParent, 0, NULL);
// Function continues...
}
DWORD WINAPI ChildThread(PVOID pvParam) {
HANDLE hThreadParent = (HANDLE) pvParam;
FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime;
GetThreadTimes(hThreadParent, &ftCreationTime,
&ftExitTime, &ftKernelTime, &ftUserTime);
CloseHandle(hThreadParent);
// Function continues...
}
当父线程运行时,它就将标识父线程所用的伪句柄转换成明确标识父线程所用的新的实句柄。同时它将这个实句柄传递给C r e a t e T h r e a d。当子线程启动运行时,它的p v P a r a m参数包含了线程的实句柄。对传递该句柄的函数的任何调用都将影响父线程而不是子线程。
由于D u p l i c a t e H a n d l e会递增特定对象的使用计数,因此当完成对复制对象句柄的使用时,应该将目标句柄传递给C l o s e H a n d l e,从而递减对象的使用计数,这一点很重要。上面的代码段已经显示出这一点。在调用G e t T h r e a d Ti m e s之后,紧接着子线程调用C l o s e H a n d l e,以便递减父线程对象的使用计数。在这个代码段中,我假设子线程不使用该句柄来调用任何其他函数。如果其他函数被调用,以便传递父线程的句柄,那么在子线程不再需要该句柄之前,不应该调用C l o s e H a n d l e。
还要指出,D u p l i c a t e H a n d l e可以用来将进程的伪句柄转换成进程的实句柄,如下面的代码所示:
HANDLE hProcess; DuplicateHandle( GetCurrentProcess(), // Handle of process that the process // pseudo-handle is relative to GetCurrentProcess(), // Process's pseudo-handle GetCurrentProcess(), // Handle of process that the new, real, // process handle is relative to &hProcess, // Will receive the new, real // handle identifying the process 0, // Ignored because of DUPLICATE_SAME_ACCESS FALSE, // New thread handle is not inheritable DUPLICATE_SAME_ACCESS); // New process handle has same // access as pseudo-handle
浙公网安备 33010602011771号