假设 Windows 伪句柄的值是不是安全/已定义?
Posted
技术标签:
【中文标题】假设 Windows 伪句柄的值是不是安全/已定义?【英文标题】:Is it safe/defined to assume the value of a Windows pseudo handle?假设 Windows 伪句柄的值是否安全/已定义? 【发布时间】:2017-08-11 09:35:18 【问题描述】:我正在为 Windows 编写一段 C++ 代码,它需要查询进程及其每个单独线程的时间。
为了进行必要的系统调用,我需要进程及其每个线程的句柄。我正在使用getCurrentProcess
和getCurrentThread
函数,它们都返回一个伪句柄。经过进一步检查,我注意到所有线程的伪句柄共享相同的值。
在互联网上进行了简短搜索后,我发现以下文章报告了与我得到的进程和线程伪句柄相同的值:https://weseetips.wordpress.com/2008/03/26/getcurrentthread-returns-pseudo-handle-not-the-real-handle/
我的问题:从一个线程调用一次getCurrentThread
并在所有其他线程中使用返回的伪句柄让它们引用自己是否安全和/或已定义?
使用当前的实现,这可以按预期工作。我只是想知道这种行为是否得到保证。换句话说,它是否可以在任何提供getCurrentThread
功能的Windows 平台上运行?改变行为是否会被视为重大改变?
documentation for the getCurrentThread
function 状态(强调我的):
伪句柄是一个特殊的常量,解释为 当前线程句柄。 调用线程可以使用这个句柄 每当需要线程句柄时指定自己。 [...]
这让我相信这个特殊的伪句柄只是“当前线程”的别名,因此可以在所有线程之间共享以让它们引用自己。另一方面,文档还说调用线程可以使用返回值,因此我很困惑!
【问题讨论】:
伪句柄类似于.
目录条目。如果您执行cd AnotherDirectory
,仍然有一个.
目录条目,但它现在指的是新的当前目录。
【参考方案1】:
是的。从同一页面:
该函数不能被一个线程使用来创建一个句柄,该句柄可以被其他线程用来引用第一个线程。 句柄总是被解释为引用正在使用它的线程。 一个线程可以为自己创建一个“真实的”句柄,它可以被其他线程使用,或者被其他进程继承,通过指定伪句柄作为调用 DuplicateHandle 函数中的源句柄。
【讨论】:
感谢您的回答。这使得伪句柄非常方便!不知道我是如何阅读那篇文档的……【参考方案2】:是的,这是安全的 - 这个伪句柄是众所周知的值,并记录在 wdm.h
(来自 windows wdk)中
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
#define ZwCurrentProcess() NtCurrentProcess()
#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 )
#define ZwCurrentThread() NtCurrentThread()
#define NtCurrentSession() ( (HANDLE)(LONG_PTR) -3 )
#define ZwCurrentSession() NtCurrentSession()
因此可以在所有线程之间共享以让它们引用 自己。
当然不,它不能“在所有线程之间共享” - 只有当前进程/线程可以使用它来引用自己。
当内核模式 api 将线程/进程句柄作为输入参数时 - 他需要将句柄转换为对象指针(ETHREAD
或 EPROCESS
)。对于此常量值的第一次检查 - 如果是 - 使用指向当前线程/进程对象的指针。否则句柄是进程句柄表中的索引
【讨论】:
当你说“只有当前进程/线程可以使用它来引用自己”时,你的意思是我需要在我的每个进程线程中调用GetCurrentThread
?还是说我不能跨进程共享?
@MaartenBamelis:您可以跨线程共享这些特殊值,但它们不是魔术。在线程 A 中,值 -2 指代线程 A。如果您与线程 B 共享该值 -2,它不会神奇地成为 A 的真实线程 ID。相反,线程 B 获得数值 -2,在线程 B 引用线程 B 而不是原来的线程 A。
@MSalters 这正是我想要的行为。但我不确定它是否是定义或保证的行为。不仅仅是未来可能发生变化的实现细节。
@MaartenBamelis:必须保证 Windows 具有向后兼容性。以上是关于假设 Windows 伪句柄的值是不是安全/已定义?的主要内容,如果未能解决你的问题,请参考以下文章
windows服务器句柄数是不是有上限?句柄过高是不是会引起服务器宕机
使用 SerialPort 和 C# 中的线程“安全句柄已关闭”
Grpc System.ObjectDisposedException:已关闭安全句柄
Microsoft.WindowsAzure.MobileServices.MobileServiceClient.PullAsync 的“安全句柄已关闭”错误