句柄图解

参考资料:http://blog.youkuaiyun.com/newjerryj/article/details/4383701

          http://www.cnblogs.com/yellowyu/archive/2009/06/07/1497910.html

写在前面:

     对于“句柄”,在下一直停留在一知半解的认识层面,近日在下学习Windows编程,决定趁此机会将句柄彻底搞清楚。查阅了一些网络上的资料,发现网络上的讲解大概可以分为两类:一种是以比喻、类比的方式说明,这种方法虽然形象易懂,但并没有从原理上、本质上加以揭示,让人仍然想问“为什么?”、“怎么实现?”。另一种是给出源代码,无可厚非,这当然是最本质的说明了,但这样一来,又显得不够直观,初学者理解起来有一定的难度。鉴于此,在下尽微末之能,结合自己的愚见,在两者之间折中,用图解的方式来将原理呈现出来,做到一目了然。

这里需要说明:

1.这里将句柄所能标识的所有东西(如窗口、文件、画笔等)统称为“对象”。

2.图中一个小横框表示一定大小的内存区域,并不代表一个字节,如标有0X00000AC6的横框表示4个字节。

3.图解的目的是为了直观易懂,所以不一定与源码完全对应,会有一定的简化。

让我们先看图,再解释。

      其中,图1是程序运行到某时刻时的内存快照,图2是程序往后运行到另一时刻时的内存快照。红色部分标出了两次的变化。

简单解释:

      Windows是一个以虚拟内存为基础的操作系统,很多时候,进程的代码和数据并不全部装入内存,进程的某一段装入内存后,还可能被换出到外存,当再次需要时,再装入内存。两次装入的地址绝大多数情况下是不一样的。也就是说,同一对象在内存中的地址会变化。(对于虚拟内存不是很了解的读者,可以参考有关操作系统方面的书籍)那么,程序怎么才能准确地访问到对象呢?为了解决这个问题,Windows引入了句柄。

      系统为每个进程在内存中分配一定的区域,用来存放各个句柄,即一个个32位无符号整型值(32位操作系统中)。每个32位无符号整型值相当于一个指针,指向内存中的另一个区域(我们不妨称之为区域A)。而区域A中存放的正是对象在内存中的地址。当对象在内存中的位置发生变化时,区域A的值被更新,变为当前时刻对象在内存中的地址,而在这个过程中,区域A的位置以及对应句柄的值是不发生变化的。这种机制,用一种形象的说法可以表述为:有一个固定的地址(句柄),指向一个固定的位置(区域A),而区域A中的值可以动态地变化,它时刻记录着当前时刻对象在内存中的地址。这样,无论对象的位置在内存中如何变化,只要我们掌握了句柄的值,就可以找到区域A,进而找到该对象。而句柄的值在程序本次运行期间是绝对不变的,我们(即系统)当然可以掌握它。这就是以不变应万变,按图索骥,顺藤摸瓜。

      所以,我们可以这样理解Windows句柄:

      数值上,是一个32位无符号整型值(32位系统下);逻辑上,相当于指针的指针;形象理解上,是Windows中各个对象的一个唯一的、固定不变的ID;作用上,Windows使用句柄来标识诸如窗口、位图、画笔等对象,并通过句柄找到这些对象。

下面,关于句柄,再交代一些关键性细节:

1.所谓“唯一”、“不变”是指在程序的一次运行中。如果本次运行完,关闭程序,再次启动程序运行,那么这次运行中,同一对象的句柄的值和上次运行时比较,一般是不一样的。

  其实这理解起来也很自然,所谓“一把归一把,这把是这把,那把是那把,两者不相干”(“把”是形象的说法,就像打牌一样,这里指程序的一次运行)。

2.句柄是对象生成时系统指定的,属性是只读的,程序员不能修改句柄。

3.不同的系统中,句柄的大小(字节数)是不同的,可以使用sizeof()来计算句柄的大小。

4.通过句柄,程序员只能调用系统提供的服务(即API调用),不能像使用指针那样,做其它的事。

写在后面:

1.到此为止,有关Windows句柄就简单介绍到这里。需要说明的是,本文是面向初学者的,旨在让读者对句柄有一个完整而清晰的认知,既要避免知其然而不知其所以然的茫然困惑,又要避免深入源码的艰难晦涩。因此,本文并不能做到绝对的直达本质,同时也可能在个别细节上与真实情况稍有出入,但在下认为这并不贻害初学者对句柄的认识。因为对某一知识的认知,从几乎一无所知或是一知半解到“精通”,往往需要更多新知识的补充,短时间内很难达到,在不影响知识的使用的前提下,先把握整体,在逐步深入细节,不失为一个明智的选择。想进一步深入理解Windows句柄的读者,可以看在下的下一篇文章《源码剖析——深入Windows句柄本质》。

2.在下知识有限,理解不深,如有错误纰漏之处,这里再三恳请大家一定要为在下指出。大家的批评指正是在下进步的源泉。

转载于:https://my.oschina.net/u/3824443/blog/2874450

在C语言中,句柄(Handle)是一个广泛使用的概念,尤其是在与操作系统或外部库交互时。句柄本质上是一个标识符,用于引用某种资源或对象。它通常是一个整数或指针,用来代表对系统资源(如文件、设备、内存块、网络连接等)的访问权限。 ### 句柄的基本概念 句柄的主要作用是提供一种间接访问资源的方式,而不是直接操作资源本身。这种方式可以提高系统的安全性和稳定性,因为资源的具体实现细节对用户是隐藏的。 例如,在Windows编程中,`HWND` 是一个句柄类型,用于表示窗口对象。在文件操作中,`FILE *` 是一个文件句柄,用于指向打开的文件流。 ### 示例:文件句柄 在C语言中,文件操作通常通过文件指针 `FILE *` 来实现。这个指针实际上就是一个句柄,它指向一个包含文件状态信息的结构体。 ```c #include <stdio.h> int main() { FILE *file = fopen("example.txt", "r"); // 打开文件并获取文件句柄 if (file == NULL) { printf("无法打开文件\n"); return 1; } // 读取文件内容 char ch; while ((ch = fgetc(file)) != EOF) { putchar(ch); } fclose(file); // 关闭文件并释放句柄 return 0; } ``` 在这个例子中,`fopen` 返回一个 `FILE *` 类型的句柄,该句柄用于后续的文件读写操作。当文件操作完成后,使用 `fclose` 关闭文件并释放句柄。 ### 图解句柄的工作原理 句柄的工作原理可以通过以下图解来理解: ``` +-------------------+ +-----------------------+ | 应用程序 | | 系统资源 | | | | | | FILE *file; | ----> | 文件描述符表 | | | | (内核中的文件信息) | +-------------------+ +-----------------------+ ``` 在这个图中,`FILE *file;` 是应用程序中的句柄,它指向系统内部维护的文件描述符表。通过这个句柄,应用程序可以间接访问文件的实际数据和状态信息。 ### 示例:Windows API 中的句柄 在 Windows API 编程中,句柄的使用非常普遍。例如,窗口句柄 `HWND` 用于表示一个窗口对象。 ```c #include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hwnd; // 窗口句柄 WNDCLASSEX wc; // 初始化窗口类结构体 wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = DefWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = "MyWindowClass"; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 注册窗口类 if (!RegisterClassEx(&wc)) { MessageBox(NULL, "窗口类注册失败!", "错误", MB_OK | MB_ICONERROR); return 0; } // 创建窗口 hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, "MyWindowClass", "我的窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if (!hwnd) { MessageBox(NULL, "窗口创建失败!", "错误", MB_OK | MB_ICONERROR); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } ``` 在这个例子中,`HWND hwnd;` 是一个窗口句柄,它用于标识创建的窗口对象。通过这个句柄,可以调用 Windows API 函数来操作窗口。 ### 总结 句柄是 C 语言中用于间接访问资源的重要机制。它提供了一种安全、高效的方式来管理系统的各种资源,如文件、窗口、设备等。通过句柄,应用程序可以与操作系统或其他库进行交互,而无需了解资源的具体实现细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值