究竟什么是句柄(handle)

本文解释了Windows编程中句柄的概念及其作用,详细介绍了句柄如何帮助应用程序安全地操作内核对象,例如进程和互斥对象。

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

当初学windows编程的时候搞不清什么是句柄,有人说其实就是个值,有人说它是个特殊的指针。什么值?特殊在哪?没人对我说明白。

 

今天刚看了《windows编程》第三章,由于知识所限,我不敢说看完了就能全面认识什么是句柄,但是,至少明白了它的概念,它在widnows应用程序中所起的作用。我仅仅希望曾经迷茫目前迷茫将来还可能迷茫的初学者们看了下面这些字之后能和我一样有个大概的了解。

 

严谨起见申明下我所指的句柄是windows应用程序的句柄,而且为了说明问题我只用了内核对象句柄作为例子,widnows应用程序用到的当然还有非内核对象句柄,如设备对象句柄。

 

在windows下写程序,多少要用到它的内核对象,比如进程内核对象,互斥内核对象……。这些内核对象就是系统的资源,出于对安全性的考虑,windows不允许在程序里直接访问这些内核对象的内存,而是通过调用它提供给我们的函数返回一个句柄,我们再用这个句柄作为执行特定行为的函数的参数去完成对内核对象的操作,比如创建一个文件映像内核对象,对它读取,写入,关闭。当然,这些函数都需要一个参数,就是我们所要操作的内核对象的句柄。

 

究竟什么是句柄?实质是什么?物理上,我们可以查看HANDLE的定义,它只不过是个几字节大小存储空间。

 

概念上我认为应该这么理解:句柄变量是个几字节大小的存储空间,而要在里面存什么,比如一个表示内存位置的指针值,或者一个整数值,甚至一个浮点数值,都不是我们需要考虑的问题,这些事情是操作系统来完成的。在windows98下或许是个进程的内核对象表的索引值(见下面的文字),在windows2000下或许只是个表示内核对象内存大小的值。在我们需要对内核对象进行操作时,通过传递给上面提到过的那些函数的句柄参数,windows会自己找到内核对象,并执行相应的操作。

 

进程的内核对象表:这里仅仅稍微描述一下,如果你想in-depth理解,那就找本好书好好学习学习。windows98给每个进程维护一个内核对象表(想知道为什么要每个进程维护一张内核对象表,看书!),只要我们在进程里创建或者打开了一个系统中已经存在的内核对象(内核对象可以在进程间共享,但是同一个内核对象的句柄值在不同进程中不一定相同),windows98就会在这个进程的内核对象表里插入一条记录,表明这个进程引用了一个内核对象,这个记录在内核对象表中的位置(索引),比如2,就返回给我们,这就是我们所需要的内核对象在这个进程中的句柄值(我反复提到“这个进程”,是因为句柄值是进程相关的,到现在你应该知道了,不同进程能使用相同的句柄值,但是不要指望它们能绝对指向同一个内核对象)!

 

千万不要先入为主,注意,上面那段字讲的仅仅是widows98操作系统拿什么作为句柄值,并不是每个系统都这么干。假设有个系统,它也打算用内核对象表的方式管理内核对象,但物理上用的是链式存储,也就是说不能直接用下标来索引内核对象在表中的位置,也即,句柄变量不能存储1,2,3……这些索引数了,那要拿什么来作为句柄变量值呢?我想,也许是链表中每个节点的地址吧^_^。

 

其实非内核对象句柄的作用也一样,都是windows防止应用程序滥用资源(这是设计操作系统的目的之一),协调windows与应用程序一起工作的手段。

 

以上纯属我个人理解,如果有误,希望你能通知我,互相学习。

### 什么是句柄? 在计算机编程中,**句柄Handle)** 是一种用于标识和访问系统资源或对象的抽象引用机制。它通常表现为一个唯一的整数值,用来代表操作系统或应用程序中的特定对象实例。这些对象可以是窗口、文件、图标、控件、设备、GDI对象等[^1]。 与指针不同,句柄并不直接指向内存地址,而是由操作系统维护的一个索引或标识符。程序通过句柄来请求对某个对象的操作权限,而无需了解该对象在系统内部的具体实现细节。这种方式增强了系统的封装性和安全性,同时也简化了资源管理的复杂性[^2]。 例如,在 Windows 编程中,句柄被广泛用于管理图形界面元素。每个窗口都有一个对应的窗口句柄(HWND),开发者可以通过这个句柄来操作窗口的属性、样式或响应事件。类似地,文件句柄用于标识打开的文件流,允许程序进行读写操作[^1]。 ### 句柄的用途 句柄的主要用途包括: - **资源管理**:操作系统使用句柄来追踪和管理各类资源,如内存分配、文件访问、网络连接等。 - **对象访问控制**:通过句柄,程序可以安全地访问系统对象,而不会直接暴露底层数据结构。 - **跨进程通信**:某些类型的句柄可以在多个进程之间共享,用于实现进程间的数据交换或同步。 - **提高程序稳定性**:由于句柄是操作系统维护的抽象标识,即使底层对象的内存地址发生变化,只要句柄有效,程序仍能正常访问对象[^2]。 ### 示例说明 在 Windows API 编程中,常见的句柄类型包括: - `HWND`:窗口句柄 - `HINSTANCE`:应用程序实例句柄 - `HDC`:设备上下文句柄 - `HANDLE`:通用句柄类型,可用于表示文件、线程、互斥量等 以下是一个简单的 Windows 窗口创建示例,展示了如何使用句柄: ```cpp #include <windows.h> LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const char CLASS_NAME[] = "SampleWindowClass"; WNDCLASS wc = {}; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; RegisterClass(&wc); HWND hwnd = CreateWindowEx( 0, CLASS_NAME, "Learn to Program Windows", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) { return 0; } ShowWindow(hwnd, nCmdShow); MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } ``` 在这个示例中,`HWND` 类型的变量 `hwnd` 就是一个窗口句柄,它用于标识并操作创建的窗口对象。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值