在Windows中讨论资源时,什么是“句柄”?它们是如何工作的?
发布于 2009-05-24 02:54:26
它是对资源的抽象引用值,通常是内存、打开的文件或管道。
正确地说,在Windows中(通常在计算中)句柄是一种抽象,它对API用户隐藏了真实的内存地址,允许系统对程序透明地重组物理内存。将句柄解析为指针会锁定内存,释放句柄会使指针失效。在这种情况下,可以将其视为指向指针表的索引...您可以将索引用于系统API调用,系统可以随意更改表中的指针。
可选地,当API编写器打算使API的用户与返回的地址所指向的细节隔离时,可以给出实际指针作为句柄;在这种情况下,必须考虑句柄所指向的内容在任何时候都可能改变(从API版本到版本,或者甚至从对返回句柄的API的调用到调用),因此应该将句柄简单地视为仅对API有意义的不透明值。
我要补充的是,在任何现代操作系统中,即使是所谓的“真实指针”也仍然是进程的虚拟内存空间的不透明句柄,这使得O/S能够管理和重新安排内存,而不会使进程中的指针无效。
发布于 2009-05-24 03:09:17
HANDLE是特定于上下文的唯一标识符。通过上下文特定,我的意思是,从一个上下文获得的句柄不一定用于任何其他也在HANDLE上工作的行为上下文中。
例如,GetModuleHandle向当前加载的模块返回唯一标识符。返回的句柄可以在接受模块句柄的其他函数中使用。它不能提供给需要其他类型句柄的函数。例如,您不能将从GetModuleHandle返回的句柄提供给HeapDestroy,并期望它做一些合理的事情。
HANDLE本身只是一个整型。通常,它是指向某个基础类型或内存位置的指针,但不是必须的。例如,GetModuleHandle返回的HANDLE实际上是指向模块的基本虚拟内存地址的指针。但是没有规则规定句柄必须是指针。句柄也可以只是一个简单的整数(它可能被一些Win32应用程序接口用作数组的索引)。
HANDLE是从内部Win32资源提供封装和抽象的故意不透明的表示。这样,Win32 API可能会更改句柄背后的底层类型,而不会以任何方式影响用户代码(至少这是这样的想法)。
考虑我刚刚编写的Win32应用程序接口的这三个不同的内部实现,并假设Widget是一个struct。
Widget * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return w;
}void * GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<void *>(w);
}typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
Widget *w;
w = findWidget(name);
return reinterpret_cast<HANDLE>(w);
}第一个示例公开了关于struct Widget的内部细节:它允许用户代码知道GetWidget返回一个指向API的指针。这有几个后果:
Widget结构的头文件Widget结构的内部部分
这两种后果可能都是不可取的。
第二个示例通过仅返回void *,对用户代码隐藏了此内部细节。用户代码不需要访问定义Widget结构的头文件。
第三个示例与第二个示例完全相同,但我们只是将void *称为HANDLE。也许这会阻碍用户代码尝试找出void *所指向的确切内容。
为什么要经历这样的麻烦呢?考虑这个相同API的更新版本的第四个示例:
typedef void * HANDLE;
HANDLE GetWidget (std::string name)
{
NewImprovedWidget *w;
w = findImprovedWidget(name);
return reinterpret_cast<HANDLE>(w);
}请注意,该函数的接口与上面的第三个示例相同。这意味着用户代码可以继续使用这个新版本的应用程序接口,而无需任何更改,即使“幕后”实现已改为使用NewImprovedWidget结构。
这些示例中的句柄实际上只是void *的一个新的、可能更友好的名称,这正是Win32应用编程接口中的HANDLE (请查看at MSDN。它在用户代码和Windows库的内部表示之间提供了一堵不透明的墙,从而增加了使用Win32应用编程接口的代码在不同版本之间的可移植性。
发布于 2009-05-24 02:58:53
Win32编程中的句柄是表示由Windows内核管理的资源的标记。句柄可以是窗口、文件等。
句柄只是一种使用Win32 API标识要使用的颗粒资源的方法。
例如,如果您想创建一个窗口,并将其显示在屏幕上,您可以执行以下操作:
// Create the window
HWND hwnd = CreateWindow(...);
if (!hwnd)
return; // hwnd not created
// Show the window.
ShowWindow(hwnd, SW_SHOW);在上面的例子中,HWND意味着“一个窗口的句柄”。
如果您习惯于面向对象的语言,您可以将句柄视为没有方法的类的实例,该类的状态只能由其他函数修改。在这种情况下,ShowWindow函数修改窗口句柄的状态。
有关详细信息,请参阅Handles and Data Types。
https://stackoverflow.com/questions/902967
复制相似问题