初识概念:句柄

来源:互联网 发布:光触媒能除甲醛吗 知乎 编辑:程序博客网 时间:2024/06/06 09:48

   一直以来,总是在各式各样的技术书籍和教材上看到“句柄”这个词,也一直觉得不影响阅读,就没去管它。

    今天,特别查一下,梳理一下这个知识点,也补上这个学习的漏洞:

————————————————————————————————————————————————

首先,百度百科:

http://baike.baidu.com/view/194921.htm

 

简单摘录:

    句柄,是整个windows编程的基础,一个句柄是指使用的一个唯一的整数值,是指一个四字节长的数值,用于标志应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等,应用程序能够通过句柄访问相应的对象的信息。但是,句柄不是一个指针,程序不能利用它句柄来直接阅读文件中的信息。如果句柄不用在I/O文件中,它是毫无用处的。 句柄是windows用来标志应用程序中建立的或是使用的唯一整数,windows使用了大量的句柄来标志很多对象。

 

—————————————————————————————————————————————————

参考资料:http://jellyfish.blogbus.com/logs/2004/08/319589.html

所谓句柄实际上是一个数据,是一个Long (整长型)的数据。

句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?

为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。


句柄地址(稳定)→记载着对象在内存中的地址————→对象在内存中的地址(不稳定)→实际对象


本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。


但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。

 

————————————————————————————————————————————————

http://hi.baidu.com/jizj06/blog/item/3055de99ebf2ea0d6f068c0f.html

 

功能上的理解:
什么是"句柄"(handle),handle的本意是把柄,把手的意思。是你与操作系统打交道的东东。
举个通俗的例子,比如你考上了大学,入学后,学校(操作系统)会给你一个学生证号。
注意,这个号码是学校指定的,你无法自选。
有了这个号码(学生证,假设一证多用)享受学校提供的服务:
如你就可以去图书馆借书,去食堂吃饭,去教室上课等等。

但你不能到食堂里买啤酒,因为学校不允许这种服务。
而在计算机中系统提供的服务就是API调用,你有了HANDLE,就可以理直气壮地向系统提出调用API的服务。
而指针的权力就大多了,有了指针你可以到处去喝酒,打架,学校(操作系统)管不着,
所以句柄和指针的区别在于句柄指针调用系统提供的服务。
而句柄虽然是一个能相互区别的号码,但与我们普通的ID号又有区别,
普通的ID号是可以由程序员自己定义的,而句柄不行,它是对象生成是系统指定的,
是为了区别系统中存在的各个对象,这个句柄不是由程序员符给的。

 

概念上的理解
1。句柄,是整个windows编程的基础,一个句柄是指使用的一个唯一的整数值,
是指一个四字节长的数值,用于标志应用程序中的不同对象和同类对象中的不同的实例,
诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。
应用程序能够通过句柄访问相应的对象的信息。
2。句柄不是一个指针,程序不能利用它句柄来直接阅读文件中的信息。
如果句柄不用在I/O文件中,它是毫无用处的。
3。句柄是windows用来标志应用程序中建立的或是使用的唯一整数,
windows使用了大量的句柄来来标志很多对象。

 

机制上的理解
前面的分析很经典,但我认为有一点必须指出的。如果不对,请各位指证。
句柄是指针,一点不假,但是这个指针又与C中的指针有不同之处。
因为Windows是一个多任务的系统,其内存是可以移动的,
这样的话如果某一时刻有一个指针指向一块内存,之后的某个时刻却被系统移走了,
如果你再用这个指针的话就会出错。
为了解决这一问题,windows在系统专区开一块内存用于存放句柄,这个句柄的值就是一个地址,
当这一块内存被移走后,windows就修改这个句柄的值,再访问这块内存时,句柄的值总是有效的。
正因为这样当你使用GlobalAlloc分配的内存时,如果你指定这块内存的属性是固定的,
那么它的返回值可以直接给一个指针,如果是可以移动的,
返回值就必须给一个句柄,你就必须先GlobalLock后才能使用。
这是我对句柄理解,不知道对不对?

 

我的理解
其实,句柄是一个指向指针的指针。即:
在windows程序设计中,句柄仅是一个应用程序用来识别某些事情的数字

如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。
我们知 道,所谓指针是一种内存地址。
应用程序启动后,组成这个程序的各对象是住留在内的。
如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。
但是,如果您真的这样认为,那么您就大错特错了。
我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,
Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。
对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,
用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。
Wi ndows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。
这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。
这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。

句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定) →实际对象
但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是
原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成
是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电
影院售给我们的门票总是不同的一个座位是一样的道理。

 

 

 

 

——-———————————————————————————————————————————————————

http://hi.baidufancys_he/blog/item/2861344affcfe32609f7efd1.html.com/

 

    句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

    从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。

    如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?

    为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。

    句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

    但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。

    受M$的帮助文档以及很多Windows编程书籍的影响,大家对局柄比较普遍的认识是:句柄是一个整数,用以标识Windows对象,句柄不是一个指针……而实际上,这些不过是M$进行数据封装的幌子而已,下面我们一起来分析一下HANDLE到底是什么。

    请先到Windef.h找绝大多数句柄的定义:

    DECLARE_HANDLE(HWND);DECLARE_HANDLE(HHOOK);……DECLARE_HANDLE(HGDIOBJ);DECLARE_HANDLE(HBITMAP);DECLARE_HANDLE(HBRUSH);……typedef HANDLE          HGLOBAL;typedef HANDLE          HLOCAL;……OK, 现在大家跟我一起翻到Winnt.h,看看DECLARE_HANDLE和HANDLE到底是什么:

    #ifdef STRICTtypedef void *HANDLE;#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name#elsetypedef PVOID HANDLE;#define DECLARE_HANDLE(name) typedef HANDLE name#endiftypedef HANDLE *PHANDLE;哈哈,现在知道了吧,HANDLE就是PVOID,也就是无类型指针,而DECLARE_HANDLE(HWND);就是:

    struct HWND__ {int unused;};typedef struct HWND__ *HWND;现在实际上都清楚啦,这些Handles都不过是指向struct的指针,至于这个struct的用处,连M$都说unused了,^o^现在解释下M$这么做的意义,这就是所谓数据封装,你可以在你的程序中把M$的内部结构指针传来传去,可是你却不知道它到底指向的内容是什么,而且可以编个句柄的瞎话防止大家的质疑:)。而M$的程序大可以这么写:

    #include <windows.h> //这个和大家用的一样#include "windows_in.h" //这个是M$自用的,外人别想看到^o^HSOMETHINGELSE DoSomething(HSOMETHING hSomething) {struct RealSomething* p = (struct RealSomething*)hSomething; //先强制类型转换成内部结构指针……do something……return (HSOMETHINGELSE)pRealSomethingElse;//强制类型逆转换 

 

原创粉丝点击