伪句柄

本文详细解析了Windows环境下线程间通信的机制,特别是如何通过`GetCurrentProcess()`和`GetCurrentThread()`函数获取伪句柄,并阐述了在实际应用中将伪句柄转换为实句柄的重要性及具体实现方式。通过实例代码,展示了如何正确地传递线程句柄以获取正确的CPU时间信息,以及在使用复制句柄函数`DuplicateHandle`时需要注意的事项,包括使用计数的管理与句柄关闭的时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

windows提供了一些函数,使线程能够很容易引用它的进程或线程的内核对象。

    HANDLE GetCurrentProcess();

    HANDLE GetCurrentThread();

    上面这两个函数都能返回调用线程的进程的伪句柄或线程内核对象的伪句柄。这些函数并不在创建进程的句柄表中创建新句柄。还有,调用这些函数对进程或线程内核对象的使用计数没有任何影响。如果调用 CloseHandle,将伪句柄作为参数来传递,那么 CloseHandle就会忽略该函数的调用并返回FALSE 。 
    有时可能需要获得线程的实句柄而不是伪句柄。所谓的“实句柄”,我是指用来明确标识一个独一无二的线程句柄。请看下面代码:

    DWORD WINAPI ParentThread(PVOID pvParam)

    {

        HANDLE hParent = GetCurrentThread();

        CreateThread(NULL,0,ChildThread,(PVOID)hParent,0,NULL);

    }

    DWORD WINAPI ChildThread(PVOID pvParam)

    {

        HANDLE hParent = (HANDLE)pvParam;

        FILETIME ftCreationTime,ftExitTime,ftKernelTime,ftUserTime;

        GetThreadTimes(hParent,&ftCreationTime,&ftExitTime,&ftKernelTime,&ftUserTime);

    }

    你能发现这个代码段存在的问题吗?这个代码的目的是让父线程给子线程传递一个线程句柄,以标识父线程。但是,父线程传递了一个伪句柄,而不是一个实句柄。当子线程开始运行时,它将一个伪句柄传递给 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函数能够执行这一转换:

    伪句柄

    通常可以使用这个函数,用与另一个进程相关的内核对象来创建一个与进程相关的新句柄。 
然而,可以用一种特殊的方法来使用这个函数,以便修改上面介绍的代码段。正确的代码段应 
该是下面的样子: 
     DWORD WINAPI ParentThread(PVOID pvParam)

    {

        HANDLE hParent;

        DuplicateHandle(

            GetCurrentProcess(),

            GetCurrentThread(),

            GetCurrentProcess(),

            &hParent,

            0,

            FALSE,

            DUPLICATE_SAME_ACCESS

        );

        

        CreateThread(NULL,0,ChildThread,(PVOID)hParent,0,NULL);

    }

    DWORD WINAPI ChildThread(PVOID pvParam)

    {

        HANDLE hParent = (HANDLE)pvParam;

        FILETIME ftCreationTime,ftExitTime,ftKernelTime,ftUserTime;

        GetThreadTimes(hParent,&ftCreationTime,&ftExitTime,&ftKernelTime,&ftUserTime);

        CloseHandle(hParent);

    }

    当父线程运行时,它就将标识父线程所用的伪句柄转换成明确标识父线程所用的新的实句柄。同时它将这个实句柄传递给 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 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值