Windows句柄介绍

2024-08-30 02:48
文章标签 windows 介绍 句柄

本文主要是介绍Windows句柄介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.句柄是什么? 
在windows中,句柄是和对象一一对应的32位无符号整数值。对象可以  映射到唯  一的句柄,句柄也可以映射到唯一的对象。 
2.为什么我们需要句柄? 
更准确地说,是windows需要句柄。windows需要向程序员提供必要地  编程接口  ,在这些接口中,允许程序员访问、创建和销毁对象。但是,出于封装地  考虑,wi  ndows并不想向程序员返回指针。指针包含了太多的信息。首先指针给出  了对象存储  的确切位置;其次,要操作一个指针,程序员必须知道指针所指对象的内  部结构特  征,也即,windows必须向程序员暴露相应的数据结构,而这些数据结构也  许是操作  系统想向程序员隐藏的。  如果说COM技术向用户隐藏了数据,只暴露了接口并只允许按接口定  义的方法操  作数据的话,句柄这种方式则允许你按自己的方式直接操作数据,但  windows又不向  你直接暴露数据。直接操作数据是程序员需要的,不暴露数据是windows所  需要的,  句柄封装方式实现了各取所需。 
3.句柄如何与对象映射? 
封装背后,必须有一个地方可以实现解码,以实现句柄和对象的相互  转换。在  windows中,存在两种映射方式: 
a. 全等映射。也即,句柄本身就是一个指针。映射在这里只是类型转  换而已。  这种情况有,进程实例句柄或模块句柄,以及资源句柄等等。 
b. 基于表格的映射。这是对象指针与句柄之间最普通的映射机制。操  作系统创  建表格,并保存所有要考虑的对象。需要创建新对象时,要先在表格中找  到空入口  ,然后把表示对象的数据添入其中。当对象被删除时,它的数据成员和其  在表中的  入口被释放。 
4.句柄的定义和实现 
我们以GDI对象为例进行讨论。创建了GDI对象,就会得到该对象的句  柄。句柄  的对象可能是HBRUSH、HPEN、HFONT或HDC中的一种,这依赖于你创  建 的GDI对象类  型。但是最普通的GDI对象类型是HGDIOBJ。HGDIOBJ被定义成空指针。  HPEN的实际编译类型定义随编译时间宏STRICT的不同而不同。如果  STRCIT已经  被定义了,HPEN是这样的: 
struct HPEN__ {int unused}; 
typedef struct HPEN__* HPEN; 
如果STRICT没有定义,HPEN是这样定义的: 
typedef void *HANDLE; 
typedef HANDLE HPEN; 
上面这段代码是一个注重细节的程序员最接近句柄的地方,因此我们重  点分析  一下。这里有一点点技巧。如果定义了STRICT宏,HPEN是指向有单个未  使用字段的  结构的指针,否则HPEN是空指针。C/C++编译器允许把任何类型的指针作  为空指什传  递,反之则不可以。两个不同类型的非空指针是互不兼容的。在STRICT版  本中,编  译对GDI对象句柄的不正确混用将给出警告,对于非GDI句柄,如HWND、 
HMENU的不正  确混用也会给出警告,从而使程序在编译器得到更STRICT的检查。  接下来的分析可能不那么令你感兴趣,但它更深刻地揭示了句柄。对  GDI句柄来  说,尽管windows头文件把它定义成指针,但如果你仔细检查这些句柄的  值,它根本  就不像指针,这也是为什么我说它只是一个32位无符整数值的原因。对句  柄就是指  针的情况,这句话也仍然适用。让我们随意地生成一些句柄,比如你用  GetStockOb  ject()以得到一些句柄,你会发现,它们的值总在区间0x01900011到  0xba040389。  前者指向用户区中的未分配的无效区域,后者指向内核地址空间。另外你 
可能发现  ,两个句柄之间的值可能只差数值1,这也说明GDI句柄不是指针。  和多数人想象的不一样,句柄也不是一个单纯的索引值。对GDI对象 
句柄来说, GDI句柄由8位 、1位堆对象标记(表明对象是否创建在堆中)、7位对象  类型信息和  高4位为0的16位索引组成,如图: 
/// 
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 
| 8 位引用计数 |堆 | 对象类型7 | 16位索引 |  标  记 
/// 
(格式问题,不好显示) 
在这里你可以看到,对GDI来说,它只使用了16位作为索引。这意味着一  个进程最多只  可以创建小于64K个句柄,实际上受其他一些限制,整个windwos系统中大  概可以容纳约  16384(0x4000)个GDI对象。 

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

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

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

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

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

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

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

这篇关于Windows句柄介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1119592

相关文章

Pytest多环境切换的常见方法介绍

《Pytest多环境切换的常见方法介绍》Pytest作为自动化测试的主力框架,如何实现本地、测试、预发、生产环境的灵活切换,本文总结了通过pytest框架实现自由环境切换的几种方法,大家可以根据需要进... 目录1.pytest-base-url2.hooks函数3.yml和fixture结论你是否也遇到过

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语

Windows Server服务器上配置FileZilla后,FTP连接不上?

《WindowsServer服务器上配置FileZilla后,FTP连接不上?》WindowsServer服务器上配置FileZilla后,FTP连接错误和操作超时的问题,应该如何解决?首先,通过... 目录在Windohttp://www.chinasem.cnws防火墙开启的情况下,遇到的错误如下:无法与

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

Python解析器安装指南分享(Mac/Windows/Linux)

《Python解析器安装指南分享(Mac/Windows/Linux)》:本文主要介绍Python解析器安装指南(Mac/Windows/Linux),具有很好的参考价值,希望对大家有所帮助,如有... 目NMNkN录1js. 安装包下载1.1 python 下载官网2.核心安装方式3. MACOS 系统安

Windows系统下如何查找JDK的安装路径

《Windows系统下如何查找JDK的安装路径》:本文主要介绍Windows系统下如何查找JDK的安装路径,文中介绍了三种方法,分别是通过命令行检查、使用verbose选项查找jre目录、以及查看... 目录一、确认是否安装了JDK二、查找路径三、另外一种方式如果很久之前安装了JDK,或者在别人的电脑上,想

Windows命令之tasklist命令用法详解(Windows查看进程)

《Windows命令之tasklist命令用法详解(Windows查看进程)》tasklist命令显示本地计算机或远程计算机上当前正在运行的进程列表,命令结合筛选器一起使用,可以按照我们的需求进行过滤... 目录命令帮助1、基本使用2、执行原理2.1、tasklist命令无法使用3、筛选器3.1、根据PID

Python中Windows和macOS文件路径格式不一致的解决方法

《Python中Windows和macOS文件路径格式不一致的解决方法》在Python中,Windows和macOS的文件路径字符串格式不一致主要体现在路径分隔符上,这种差异可能导致跨平台代码在处理文... 目录方法 1:使用 os.path 模块方法 2:使用 pathlib 模块(推荐)方法 3:统一使