windows句柄,其实是在说这么一个类型: HANDLE,在windows.h里面,是这样定义的:LPVOID,其实就是一个void*。
对于很多新手来说,句柄这个概念有点难以理解。
想要真正了解句柄,你必须首先要了解内核对象。不了解内核对象而空谈句柄,没有任何的意义。
windows内核对象是由操作系统内核分配的一块内存(储存着对象的相关信息), 这段内存只能由内核访问和管理。
1. SEMAPHORE对象,用于线程同步
2. event对象,用于线程同步
3. file对象 文件
4. mapped file对象 映射文件
5. IO完成端口
6. 作业对象 job
7. 互斥对象 mutex,用于线程同步
8. 管道对象 pipe,用于进程间通信
9. 进程对象 process
10. 线程对象 thread
11. 待计时器对象 timer
12。线程池对象。
等等,这里并没有完全列出。
这个由内核所分配的内存块本质上是一种数据结构,不同的内核对象有不同的结构成员,但几乎所有的内核对象都有以下两个重要的成员:
1) 使用计数器 (use count)
用于记录当前有多少个进程在使用该内核对象--当内核对像被首次创建时其计数为1,然后,每次有另外的进程访问该对象时,计数器+1,当一个进 程结束时系统会自动检查被该进程所使用的那些在内存中依然的内核对象的usage count,并将其减1,此时,如果减后的usage count为0,那么系统会进一步自动撤销该内核对像。这样便可以保证没有被任何进程使用的kernel object的内存被及时撤销。
2)安全描述符(security discriptor)
安全描述符用于描述谁创建了该对象,谁能够访问或使用该对象,谁无权访问该对象。安全描述符通常在编写服务器应用程序时使用,如果你编写客户机端的应用程 序,那么可以忽略内核对象的这个特性。另外,该成员也是所创建的对象是否为内核的依据。大多数应用程序只是为该参数传递N U L L,这样就可以创建带有默认安全性的内核对象。默认安全性意味着对象的管理小组的任何成员和对象的创建者都拥有对该对象的全部访问权,而其他所有人均无权 访问该对象。但是,可以指定一个SECUTITY_ATTRIBUTES结构,对它进行初始化,并为该参数传递该结构的地址。
区别内核对象和用户对象的方法是,看对象的创建函数,一般的内核对象的创建函数最后一个参数都是安全描述符相关的。而用户对象则没有。一些UI相关的handle,Menu,icon,image不是内核对象。
鉴于内核对象不能被应用程序直接访问,为了让应用程序方便的使用内核对象,微软设计了句柄,用句柄来关联一个内核对象。使得应用程序只能通过句柄的 方式并调用windows提供的一系列内核对象操作接口,而且这些句柄对于应用程序来说是不透明的。这就是句柄设计的目的。当创建一个内核对象时,返回的 是和这个内核对象关联的句柄。而使用句柄则丧失了许多权限,使得内核对象安全得到了保证。
一般来说,句柄都是依附于进程的。但是句柄也可以跨进程共享。每个进程都有一张表,用来储存自身所创建和拥有的内核对象的指针,而句柄则是这些指针在表的索引值。从hande到索引会有一个变换,一般是除4。但是不同的版本会不一样。