内核知道有多少进程正在使用某个内核对象,因为每个对象包含一个使用计数。使用计数是所有内核对象类型常用的数据成员之一。当一个对象刚刚创建时,它的使用计数被置为1。然后,当另一个进程访问一个现有的内核对象时,使用计数就递增1。当进程终止运行时,内核就自动确定该进程仍然打开的所有内核对象的使用计数。如果内核对象的使用计数降为0,内核就撤消该对象。这样可以确保在没有进程引用该对象时系统中不保留任何内核对象。
除了内核对象外,你的应用程序也可以使用其他类型的对象,如菜单、窗口、鼠标光标、
刷子和字体等。这些对象属于用户对象或图形设备接口( G D I)对象,而不是内核对象。当初
次着手为Wi n d o w s编程时,如果想要将用户对象或G D I对象与内核对象区分开来,你一定会感
到不知所措。比如,图标究竟是用户对象还是内核对象呢?若要确定一个对象是否属于内核对
象,最容易的方法是观察创建该对象所用的函数。创建内核对象的所有函数几乎都有一个参数,
你可以用来设定安全属性的信息,这与前面讲到的C r e a t e F i l e M a p p i n g函数是相同的。
用于创建用户对象或G D I对象
关闭内核对象
无论怎样创建内核对象,都要向系统指明将通过调用C l o s e H a n d l e来结束对该对象的操作:
BOOL CloseHandle(Handle obj);
该函数首先检查调用进程的句柄表,以确保传递给它的索引(句柄)用于标识一个进程实际
上无权访问的对象。如果该索引是有效的,那么系统就可以获得内核对象的数据结构的地址,并
可确定该结构中的使用计数的数据成员。如果使用计数是0,该内核便从内存中撤消该内核对象。
假如忘记调用C l o s e H a n d l e函数,那么会不会出现内存泄漏呢?答案是可能的,但是也不
一定。在进程运行时,进程有可能泄漏资源(如内核对象)。但是,当进程终止运行时,操作
系统能够确保该进程使用的任何资源或全部资源均被释放,这是有保证的。对于内核对象来说,
系统将执行下列操作:当进程终止运行时,系统会自动扫描进程的句柄表。如果该表拥有任何
无效项目(即在终止进程运行前没有关闭的对象),系统将关闭这些对象句柄。如果这些对象
中的任何对象的使用计数降为0,那么内核便撤消该对象。因此,应用程序在运行时有可能泄漏内核对象