Windows程序基础二:句柄、HINSTANCE句柄

1、句柄:一个特殊的数据类型

     定义:句柄,Handle,是整个Windows编程的基础。一个句柄是指使用的一个惟一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不一样对象和同类对象中的不一样的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序可以经过句柄访问相应的对象的信息,可是句柄不是一个指针,程序不能利用句柄来直接阅读文件中的信息。若是句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中创建的或是使用的惟一整数,Windows使用了大量的句柄来标识不少对象。
     在Windows程序中,常常可心看到用相似HPEN、HFONT这样以字母H开头的数据类型来声明或定义的“变量”,例如WinMain()函数参数列表中的HINSTANCE hInstance
这里的HINSTANCE类型的"变量"hInstance就是一个所谓的句柄,前面的HINSTANCE表示了一种句柄类型。句柄这种类型变量用来表示一个内核对象。
     Windows操做系统之上的用户应用程序,必然会用到结构来描述一些须要大量数据来描述的窗口、按钮、文本框、滚动条等这种描述了事物的数据结构实例都叫作对象。出于用户的方便,系统的安全及保护知识产权等多种考虑,微软公司虽然在Windows系统中定义了这些数据结构,但并未向用户公开,所以,为了使用用户应用程序能够建立并得到这种对象,Windows在API中提供了相应的服务函数,用户经过调用这种函数得到由系统建立的对象。因为使用这种方法建立的对象位于内核内存空间,故称做内核对象。可是必须注意,为了系统安全和隐藏内核对象的实现细节,用户调用API函数建立内核对象成功以后,函数为用户返回的既不是该结构实例自己,也不是其指针,而是Windows操做系统为这个内核对象所编制的一个4字节的整数临时编号,而这个编号也仅在本应用程序中有效。为了程序的可读性,并根据这个编号的用途,Windows为这种存放了内核对象临时编号的整型数据变量定义了一个别名:“句柄(Handle)”。Windows的内核对象及其够本类型以下:
表1  Windows经常使用句柄类型

从表中可知,把这种类型变量叫作句柄类型,是由于与生活中的刀柄、壶柄的做用极为相似,意思就是说用户只要得到了句柄,那么也就得到了安装在内核对象上的“手柄”,就能在不直接接触这个对象的状况下进行操做。句柄是一个标识符,是拿来标识对象或者项目的。它就像咱们的车牌号同样,每一辆注册过的车都会有一个肯定的号码,不一样的车号码各不相同,可是也可能会在不一样的时期出现两辆号码相同的车,只不过它们不会同时处于使用之中罢了。     其实,这种够本实质上结构类弄变量指针的再封装,从面避免用户直接操做指针而产生的危险,而且因期隔离做用屏蔽了对象的实现细节,还起到了代码的保密做用。还有一个优势开发者能够在不改变用户全部句柄的前提下,更换可更新与之关联的内核对象,从而能够在不修改用户用户程序的状况下为系统进行升级换代。这就是现代程序设计中的代码弱耦合或代码隔离技术。
    Windows 之因此要设立句柄,根本上源于内存管理机制的问题—虚拟地址,简而言之数据的地址须要变更,变更之后就须要有人来记录管理变更,(就好像户籍管理同样),所以系统用句柄来记载数据地址的变动。数据对象加载进入内存中以后即得到了地址,可是这个地址并非固定的,(至于为何以及什么状况下变更具体须要你们研究虚拟地址的原理与机制我这里只提我肯定知道的例子)数据对象会根据须要在内存与硬盘之间游弋移动(例如不经常使用的数据会为经常使用数据让出其占用的内存空间进而被淘汰进硬盘中的虚拟内存之中以优化配置总体系统的资源进而提高效率性能),所以其物理地址老是变更的,那么做为管理者 则必须对 管理对象所发生的变化了如指掌才行,所以系统为进程分配固定的地址(句柄)来存储进程下的数据对象变化后的地址也就是当前的地址,其实设计机制很简单 :系统的某个部门移动了对象的地址后,同时上报给句柄所属部门管理者,管理者将改动写入句柄便可。该数据被从新起用时去其所属句柄内按内容存取便可。
    句柄,在Windows编程中是一个很重要的概念,在许多地方都扮演着重要的角色。但由此而产生的句柄概念也大同小异,好比:《Microsoft Windows 3 Developer's Workshop》(Microsoft Press,by Richard Wilton)一书中句柄的概念是:在Windows环境中,句柄是用来标识项目的。在程序设计中,句柄是一种特殊的智能指针 。当一个应用程序要引用其余系统(如数据库、操做系统)所管理的内存块或对象时,就要使用句柄。
   句柄与普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识,该标识能够被系统从新定位到一个内存地址上。这种间接访问对象的模式加强了系统对引用对象的控制。在上世纪80年代的操做系统(如Mac OS 和Windows)的内存管理中,句柄被普遍应用。Unix系统的文件描述符基本上也属于句柄。和其它桌面环境同样,WindowsAPI大量使用句柄来标识系统中的对象,并创建操做系统与用户空间之间的通讯渠道。例如,桌面上的一个窗体由一个HWND类型的句柄来标识。现在,内存容量的增大和虚拟内存算法使得更简单的指针越发受到青睐,而指向另外一指针的那类句柄受到冷淡。尽管如此,许多操做系统仍然把指向私有对象的指针以及进程传递给客户端的内部数组下标称为句柄。

2、HINSTANCE句柄

           初学者在学习和阅读Windows程序时, 经常会因一开始便遇到这种极其陌生的数据类型而感到极大的压力。其实,初学者彻底没有必要紧张,由于在Windwos程序设计中也不多用到对INSTANCE类型内核对象进行操做的状况,故能够暂时不理它,另外它与其余句柄同样,也仅表明一个内核对象,只不过这个内核对象是一个正在运行着的程序。
int WINAPI WinMain(
HINSTANCE hInstance,		//当前应用程序实例的句柄
HINSTANCE hPrevInstance,	//系统中前一个应用程序实例的句柄,不多用到
LPSTR	lpCmdLine,			//指向本程序命令行的指针,不多用到
int nCmdShow				//决定应用程序窗口显示方式的标志
         hInstance是程序的当前实例的句柄。在Windows这样的多任务操做系统中,一个程序能够同时运行多个实例。不一样的实例间须要彼此区别,句柄就是干这个的。通常在操做系统看来,在运行一个程序时,要先创建一个结构变量,以便在程序运行起来以后在这个结构中记录该程序的的运行进度、状态、内存占用状况、文件和外设的使用状况等,并进行管理。换言之,Windows操做系统是经过这个与程序代码相关联的数据结构变量为掌控一个程序的运行。Windows中的这种用以表示一个程序运行过程的内核对象,叫作进行对象或进程,或叫“进程控制块”,具体的结构代码没公布,不过hInstance就是指向此进程块的句柄。    
    Windows每运行一个程序,就会在系统中建立一个该程序的HINSTANCE类型内核对象,图1中运行着3个进行的状况,在这个3个进程中,虽然进程1和进程2运行的都是程序1代码,但因为不是同一个控制块,故这是同一个程序的两个运行,所以在系统中也就存在着两个实例,即两个进程。即若是用户启动了两个QQ,那么在系统中就有两个QQ实例句柄存在。  
  

图1 HINSTANCE类型句柄的概念
        总之,这种类型的句柄表明了正在运行的当作是Windows定义的一个新数据类型——程序类型,而其对象则至关是一个程序类型的变量,这个变量就表明了一个正在运行的程序,Windows每运行一个程序就会把该程序的指针赋予这个变量,程序可使用这个变量对一个程序进行操做。尽管这样看不严格,但不会特别影响咱们的使用。