`
liuzhifu123
  • 浏览: 36162 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

句柄的本质

 
阅读更多

一、书上定义:

<<Microsoft Windows 3 Developer''s Workshop>>(Microsoft Press,by Richard Wilton)
    在Windows环境中,句柄是用来标识项目的,这些项目包括:模块(module)、任务(task)、实例 (instance)、文件(file)、内存块(block of memory)、菜单(menu)、控制(control)、字体(font)、资源(resource),包括图标(icon),光标 (cursor),字符串(string)等、GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域 (region),以及设备描述表(device context)。 

<<WINDOWS编程短平快>>(南京大学出版社):
    句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。 

二、MFC源代码:

#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif

DECLARE_HANDLE(HMODULE); 
DECLARE_HANDLE(HINSTANCE); 
DECLARE_HANDLE(HLOCAL); 
DECLARE_HANDLE(HGLOBAL); 
DECLARE_HANDLE(HDC); 
DECLARE_HANDLE(HRGN); 
DECLARE_HANDLE(HWND); 
DECLARE_HANDLE(HMENU); 
DECLARE_HANDLE(HACCEL); 
DECLARE_HANDLE(HTASK); 


三、理解:
    HANDLE就是PVOID,也就是无类型指针,
    上面这些资源的句柄Handles都不过是指向struct的指针,至于这个struct的用处,连M$都说unused了,现在解释下M$这么做的意义,这就是所谓数据封装,你可以在你的程序中把M$的内部结构指针传来传去,可是你却不知道它到底指向的内容是什么。

    句柄与指针确实是完全不同的两个概念。句柄仅仅是一个32位整数,WIN32中用于标记某个系统或进程的对象,可以理解为对象索引(由于M$未完全公开相关技术,在一定程度上只能如此理解),这个索引更像是一种映射关系(从句柄到对象指针的映射),而不是纯粹意义上的“数组下标”。 


     句柄可以理解为用于指向或标识内存的一块“资源”,这些资源如:文件(file)、内存块(block of memory)、菜单(menu)等等。操作系统通过句柄来定位核心对象和系统资源。
    指针即为指向内存的“数据或指令”某一单元。

    说的确切一点,句柄实际上是一种指向某种资源的指针,但与指针又有所不同:指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。

    
四、引喻:
   牧童遥指杏花村
   牧童的手为指针,杏花村的牌子为句柄,杏花村酒店为对象的实例. 


附注:获得窗口句柄三种方法

1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName) 

   HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName) 

2.HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND

3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)

   BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)

   BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

   BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

 

从广义上,能够从一个数值拎起一大堆数据的东西都可以叫做句柄。句柄的英文是"Handle",本义就是"柄",只是在计算机科学中,被特别地翻译成"句柄",其实还是个"柄"。从一个小东西拎起一大堆东西,这难道不像是个"柄"吗?

然后,指针其实也是一种"句柄",只是由于指针同时拥有更特殊的含义——实实在在地对应内存里地一个地址——所以,通常不把指针说成是"句柄"。但指针也有着能从一个32位的值引用到一大堆数据的作用,这不是句柄又是什么?

Windows系统中有许多内核对象(这里的对象不完全等价于"面向对象程序设计"一词中的"对象",虽然实质上还真差不多),比如打开的文件,创建的线程,程序的窗口,等等。这些重要的对象肯定不是4个字节或者8个字节足以完全描述的,他们拥有大量的属性。为了保存这样一个"对象"的状态,往往需要上百甚至上千字节的内存空间,那么怎么在程序间或程序内部的子过程(函数)之间传递这些数据呢?拖着这成百上千的字节拷贝来拷贝去吗?显然会浪费效率。那么怎么办?当然传递这些对象的首地址是一个办法,但这至少有两个缺点:

  1. 暴露了内核对象本身,使得程序(而不是操作系统内核)也可以任意地修改对象地内部状态(首地址都知道了,还有什么不能改的?),这显然是操作系统内核所不允许的;
  2. 操作系统有定期整理内存的责任,如果一些内存整理过一次后,对象被搬走了怎么办?

所以,Windows操作系统就采用进一步的间接:在进程的地址空间中设一张表,表里头专门保存一些编号和由这个编号对应一个地址,而由那个地址去引用实际的对象,这个编号跟那个地址在数值上没有任何规律性的联系,纯粹是个映射而已。

在Windows系统中,这个编号就叫做"句柄"。

 

Handle在Windows中的含义很广泛,以下关于谈到的Handle除非特别说明,将仅限于进程、线程的上下文中。

1、先来谈谈Handle

Handle本身是一个32位的无符号整数,它用来代表一个内核对象。它并不指向实际的内核对象,用户模式下的程序永远不可能获得一个内核对象的实际地址(一般情况下)。那么Handle的意义何在?它实际上是作为一个索引在一个表中查找对应的内核对象的实际地址。那么这个表在哪里呢?每个进程都有这样的一个表,叫句柄表。该表的第一项就是进程自己的句柄,这也是为什么你调用GetCurrentProcess()总是返回0x7FFFFFFF原因。

简单地说,Handle就是一种用来"间接"代表一个内核对象的整数值。你可以在程序中使用handle来代表你想要操作的内核对象。这里的内核对象包括:事件(Event)、线程、进程、Mutex等等。我们最常见的就是文件句柄(file handle)。

另外要注意的是,Handle仅在其所属的进程中才有意义。将一个进程拥有的handle传给另一个进程没有任何意义,如果非要这么做,则需要使用DuplicateHandle(),在多个进程间传递Handle是另外一个话题了,与这里要讨论的无关。

2、进程ID

首先,进程ID是一个32位无符号整数,每个进程都有这样的一个ID,并且该ID在系统范围内是唯一的。系统使用该ID来唯一确定一个进程。

深入些说,系统可能使用进程ID来计算代表该进程的内核对象的基地址(及EPROCESS结构的基地址),具体的计算公式你可以去问微软的OS开发人员。

3、HINSTANCE

HINSTANCE也是一个32无符号整数,它表示程序加载到内存中的基地址。

分享到:
评论

相关推荐

    句柄之深入解析

    在某些特殊场景下,可能需要进行指针和句柄之间的转换,这通常涉及到较为底层的操作,需要注意的是,这种转换并不是总是可行的,因为句柄本质上是对对象的间接引用,而指针则是直接引用。 总之,句柄是Windows编程...

    句柄查看精灵 3.0

    首先,我们要理解句柄的本质。句柄不是资源本身,而是一个指向资源的引用或者索引。操作系统通过句柄管理内存、文件、设备等资源,使得进程可以安全地访问这些资源,而不需要知道资源在内存中的具体位置。每个句柄都...

    通过进程ID找到窗口句柄.

    通过进程ID找到窗口句柄的过程,实质上就是在操作系统层面定位到特定进程中的某个或某些窗口,并获取其句柄以便进一步操作。 #### 二、关键系统函数 要实现这一功能,我们需要调用两个关键的Windows API函数:`...

    什么是句柄-之一

    句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象本质 句柄的具体含义受 M$ 的帮助文档以及很多 Windows 编程书籍的影响,大家对句柄的认识是:句柄是一个整数,用以...

    遍历已知父窗里子窗所有句柄

    `.NET`的`foreach`循环可以简化遍历过程,但本质上仍然是对`EnumChildWindows`的封装。 总之,遍历已知父窗口的子窗口句柄是通过Windows API实现的,涉及到的主要函数有`FindWindow`、`EnumChildWindows`以及一些...

    句柄和指针的区别

    **句柄**与**指针**虽然在表面上看似相似,但在计算机编程尤其是Windows环境下,它们有着本质的区别。理解这两种概念的不同对于掌握Windows编程至关重要。 #### 二、句柄的概念 - **定义**:句柄是Windows操作系统...

    什么是句柄

    句柄的本质是一个指向特定资源的引用,它并不直接包含资源本身的信息,而是一个间接的索引或标识符。在Windows操作系统中,句柄通常是一个32位或64位的无符号整数,用于在进程的句柄表中定位对应的内核对象。这些...

    VC++中句柄与指针的区别

    无论它的本质是什么,句柄并不是一个真正意义上的指针。从构造上看,句柄是一个指针尽管它没有指向用于存储某个对象的内存位置。事实上,句柄指向一个包含了对该对象进行的引用的位置。 Windows是一个多任务操作...

    句柄的本质——拨乱反正篇.docx

    在深入探讨句柄的本质之前,我们首先需要理解什么是句柄。在Windows编程中,句柄(Handle)是一种用于标识系统对象(如窗口、设备、内存块等)的抽象标识符。通常,人们认为句柄是一个整数值,它不是指针,而是由...

    C++中句柄和指针的区别

    它本质上是一个数值,通过这个数值可以间接访问和操作内存中的对象。在操作系统层面,句柄常常被用作一种安全的接口,用于封装对系统资源的引用。例如,在Windows操作系统中,句柄是一个32位无符号整数,它代表了...

    WONDOWS句柄

    句柄(Handle)是Windows系统中用于标识和管理各种资源的一种机制,它实质上是一个非零正整数,用作操作系统内部资源的引用或索引。句柄的设计初衷是为了提供一种安全、灵活且高效的方式来访问和控制操作系统中的...

    MATLAB图形句柄.doc

    然而,底层绘图和高层绘图存在本质的区别。高层绘图函数(如plot、bar、pie等)提供了快速绘制基础图形的简便方法,它们适合快速生成图表,但在需要精细调整时,其功能就会显得不足。相对地,底层绘图通过句柄图形,...

    什么是句柄-之二

    `DECLARE_HANDLE`宏被用来定义这些特定的句柄类型,本质上它们都是`HANDLE`的别名,确保了句柄的一致性和兼容性。 句柄的获取通常通过调用Windows API函数实现,如`CreateWindow`、`GlobalAlloc`、`OpenFile`等。...

    pspCidTAble完全解读

    这表明句柄本质上是一个32位的无符号指针,用来充当内核对象的索引。每个进程都有自己的句柄表,当进程需要操作内核对象时,系统会将对象的指针放入该进程的句柄表中,并返回一个句柄。通过这个句柄,进程可以索引到...

    内存句柄与指针的区别.pdf

    句柄是一个整数,它在本质上是一个索引,指向一个系统维护的内部表,这个表包含了对象的相关信息。句柄提供了一种安全的方式来访问和操作对象,因为它不直接暴露对象在内存中的地址,因此不能被误用或滥用来修改不...

    VB与_Windows_API_讲座(1-5完整版).pdf

    句柄本质上是一个标识符,用于唯一地标识系统中的各项资源,如窗口、菜单、图像、内存块等。通过句柄,开发者可以请求操作系统执行特定操作,如更改窗口标题、显示图像或更新菜单。 #### 五、SetWindowText函数详解...

    Pro/E二次开发基本方法研究

    - 句柄本质上是一个指针地址的指针,用于保存指针地址。 - 句柄与对象地址之间的关系在程序重启时通常会改变。 - 在Pro/Toolkit中,句柄主要分为两种类型:不透明句柄(Ohandle)和明确定义的句柄。 4. 使用MFC...

    windows编程的简介

    句柄实质上是指向指针的指针,常见的句柄类型包括: - `HWND`:窗口句柄。 - `HINSTANCE`:应用程序实例句柄。 - `HDC`:设备环境句柄。 - `HBITMAP`:位图句柄。 - `HFILE`:文件句柄。 #### 数据类型 Windows...

    win32+sdk教程与基础

    句柄本质上是一个整数,用于唯一标识一个对象,如窗口、设备上下文、菜单等。通过句柄可以访问和操纵这些对象。 ##### 3. 回调 (Callback) 回调是在编程中常用的一种技术,特别是在事件驱动编程中。在 Win32 编程中...

    《Windows核心编程系列》谈谈内核对象及句柄的本质

    本章讨论的是相对抽象的概念,不涉及任何具体的内核...调用创建内核对象的函数后,该函数会返回一个句柄,它标识了所创建的对象。它可以由进程的任何线程使用。在32位系统中,句柄是一个32位值。64位系统中则是64位值。

Global site tag (gtag.js) - Google Analytics