进程的内核对象句柄表-程序员宅基地

技术标签: access  null  attributes  数据结构  table  object  

进程的内核对象句柄表

 

当进程初始化的时候,系统会为其分配一个句柄表(handle table )。该句柄表只用于内核对象 ,不适用于用户对象或GDI对象。 具体该句柄表在系统中是种怎样的结构和是怎么被系统管理的,现在没有说明文档。 进程句柄表的大体结构如下:

 

Index                       Pointer to Kernel object memory block              Access Mask          Flags

 

 

创建一个内核对象

当进程被初始化之后,其句柄表是空的。当进程内的一线程通过指定的函数创建了 一个内核对象时,内核会为对象分配一块内存区域并初始化这块区域。然后内核 会在进程的句柄表中查找一个空的入口,找到之后会初始化句柄表的以索引定位 的区域。初始化的主要过程就是填充句柄表的一个单元,包括指定内核对象地址, 指定访问码,指定标记等。
    以下是用于创建内核对象的一些函数:

 

HANDLE CreateThread(
                    PSECURITY_ATTRIBUTES psa,
                    size_t dwStackSize,
                    LPTHREAD_START_ROUTINE pfnStartAddress,
                    PVOID pvParam,
                    DWORD dwCreationFlags,
                    PDWORD pdwThreadId);

HANDLE CreateFile(
                  PCTSTR pszFileName,
                  DWORD dwDesiredAccess,
                  DWORD dwShareMode,
                  PSECURITY_ATTRIBUTES psa,
                  DWORD dwCreationDisposition,
                  DWORD dwFlagsAndAttributes,
                  HANDLE hTemplateFile);

HANDLE CreateFileMapping(
                         HANDLE hFile,
                         PSECURITY_ATTRIBUTES psa,
                         DWORD flProtect,
                         DWORD dwMaximumSizeHigh,
                         DWORD dwMaximumSizeLow,
                         PCTSTR pszName);

HANDLE CreateSemaphore(
                       PSECURITY_ATTRIBUTES psa,
                       LONG lInitialCount,
                       LONG lMaximumCount,
                       PCTSTR pszName);

 

 

所有创建内核对象的函数都会返回一个与进程相关的句柄, 该句柄可被进程内的任何线程使用。这个句柄实际上是可以被4整除的,其结果就是内核对象在句柄表中的索引号。

      当调用需要以内核对象句柄为参数的函数时,你就可以先创建一个内核对象,然后将创建函数的返回值传递给下一个需要句柄作参数的函数。在内部的实现上, 该函数其实是在进程的内核对象句柄表中查找你想操作的内核对象的地址,然后会以一种良好的方式操作内核对象的数据结构。

      当你传递一个非法的句柄时,调用的函数会返回错误,通过GetLastError会得到 6(ERROR_INVALID_HANDLE),因为句柄会被当作句柄表的索引值,且句柄是与进程关联在一起的 ,可以被其它进程使用。如果你曾尝试着这么做的话,其结果是引用了其它进程的同索引号的内核对象,你不知道你引用的究竟是何对象。

      如果你调用创建内核的函数失败时,函数通常会返回0(NULL),这也就是为什么内核对象的第一个可用句柄值是4的原因。系统通常对于这种安全性检查做得不够,不幸的是,有些函数创建失败时会返回-1,即INVALID_HANDLE_VALUE,所以当你 检查创建内核对象是否成功时一定要小心,不能统一地将函数的返回值与NULL进行 比较。其实,只要知道一些特殊情况就可以了,当你调用CreateFile时,就要记住 它失败时会返回-1,所以检查它是否正确执行时将返回值和INVALID_HANDLE_VALUE 比较即可。

两个错误比较的例子如下:
*/
HANDLE hMutex = CreateMutex(…);
if (hMutex == INVALID_HANDLE_VALUE) {
    // We will never execute this code because
    // CreateMutex returns NULL if it fails.
}


HANDLE hFile = CreateFile(…);
if (hFile == NULL) {
    // We will never execute this code because CreateFile
    // returns INVALID_HANDLE_VALUE (-1) if it fails.
}

/*
    关闭内核对象:

    不管你以何种方式创建了一个内核对象,当你用完它时,你应该通知系统你用完了通知的方式就是调用函数:
*/
    BOOL CloseHandle(HANDLE hobject);
/*

    在内部机理上,该函数会首先检查进程的句柄表以确认传递给它的句柄所标记的 内核对象进程确实有访问它的权限。如果句柄有效,系统会获取句柄所标记的内核 对象的地址并减小使用次数这一数据成员。如果使用次数变成了0,内核对象会 被销毁并在内存中删除。如果传递给CloseHandle的是一个无效句柄,此时可能会有两件事发生。如果你的 进程运行正常,CloseHandle会返回FALSE,此时GetLastError会返回无效句柄的 标识ERROR_INVALID_HANDLE;但你的进程此时正在被调试,系统会抛出异常 0XC0000008(指定了无效的句柄),此时我们就可以根据异常来调试代码了。

    在函数CloseHandle返回之后,进程句柄表中被关于的句柄会被清除,意思就是说 关闭之后的句柄对关闭其的进程无效了,我们不能再尝试使用它。句柄在句柄表 中的清除与句柄所代表的内核对象的销毁并无直接关系,即如果句柄被清除了, 但其先前所代表的内核对象及可能存在于内核中。关闭句柄的意思就是进程已无 访问句柄所代表的内核对象的权限了。内核对象的存在与否决定于其数据成员--使用次数。如果使用次数不为0,说明还有其它进程在使用它,此时内核不能销毁 对象,只有当内核对象的使用次数变成0的时候,内核才会销毁对象。

    注意点:
        使用句柄同使用指针一样需要注意很多,多数情况下我们会将内核对象的句 柄关联到一个成员变量。当我们调用了CloseHandle之后就宣布了句柄的无效, 此时也应该将句柄先前关联的成员变量设置为NULL,以防不经意再次使用它。

 

    再说一说忘记调用CloseHandle的问题吧,如果忘记通过该函数关闭内核对象的 句柄,只能说可能会发生对象泄漏。在进程运行的过程中,可能由于忘记关闭 句柄导致对象泄漏,但一旦进程结束后,系统会检查进程的句柄表,如果发现有 未关闭的句柄,系统会帮你关闭句柄。此时如果句柄所代表的内核对象的使用 次数变成0,内核会去销毁内核对象。这样就保证不会出现内存和资源的泄漏。由上可知,内核对象的泄漏只能发生在进程执行的过程中,进程结束之后,系统 保证会妥善地清除该进程使用的所有资源。这种机制对所有对象,资源如GDI对象, 内存块都是有效的。当进程结束之后,系统会收回进程使用的所有资源。

 

本文来自程序员宅基地,转载请标明出处:http://blog.csdn.net/thankall/archive/2008/09/10/2909548.aspx

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wowbell/article/details/6160668

智能推荐

git commit提交报错subject may not be empty [subject-empty]-程序员宅基地

文章浏览阅读2.3w次,点赞10次,收藏7次。今天在sourcetree提交写好的代码突然报错,显示如下错误: subject may not be empty [subject-empty] type may not be empty [type-empty]_subject may not be empty

FS102WS是一款用于 LED 灯光开关控制及亮度调节的触摸IC-程序员宅基地

文章浏览阅读187次。每次短按触摸,依OPT1/2/3选择不同,灯光亮度按[高亮度→>中亮度->低亮度->灭]依次循环变化,或[低亮度->中亮度->高亮度->灭]依次循环变化。FS102WS是一款用于 LED 灯光开关控制及亮度调节的触摸IC,支持单通道触摸输入、单路 PWM 输出,可在有介质(如玻璃、亚克力、塑料、陶瓷等)隔离保护的情况下实现触摸功能,可靠性非常高,灯光无闪频。未断电短按开灯后第一次长按调光的方向由之前记忆的亮度值来决定,若记忆亮度值大于45%,则向下调光:若记忆亮度值小于45%,则向上调光。

Python办公自动化实战 09 | Python-docx库:Python与Word的完美结合_ 如何在Word中生成表格?把Python办公自动化进行到底-程序员宅基地

文章浏览阅读911次。本小节主要演示了怎么向Word文档中创建表格并插入数据,并且对表格格式做个性化的设定。_python与word的完美结合

MySQL:从库binlog 使用mysqlbinlog stop-datetime过滤问题-程序员宅基地

文章浏览阅读2k次。更多主从同步相关可以参考我的《深入理解MySQL主从原理》专栏:本文是一个朋友问我问题。从库使用mysqlbinlog..._mysql stop-datetime

SAP入门经验_sap经验-程序员宅基地

文章浏览阅读8k次,点赞18次,收藏30次。SAP入门的经验SAP业务顾问入门确实起点比较高,这在我最开始入门的时候不以为然,但是随着学习的深入,才发现原来老师们说的是真的!简单说一下我自己的入门经历,我是本科是工业工程(IE)专业的,如果有了解的肯定知道这个专业是干什么的,步入这个行业我才发现我所学的专业知识都挺有用的,特别是PP模块,我本身在大学就经常参加一些生产优化案例竞赛,对于排产,MRP等信息有了初步的了解,更重要的是IE专业培养了我的优化意识我感觉这是我的一大笔财富。好了步入正题,说一下我的入门经历:最开始公司培训讲了很多模块的知_sap经验

C++中派生类成员变量和基类成员变量同名问题_c++ 在派生类函数中修改基类同名变量-程序员宅基地

文章浏览阅读8.8k次,点赞5次,收藏18次。1.当派生类存在与基类同名的成员变量时候,派生类的成员会隐藏基类成员,但派生类中存在基类成员的拷贝,要显示的访问BASE::date member#include <iostream>using namespace std;class Base{ public: int a = 10; void print() { cout &..._c++ 在派生类函数中修改基类同名变量

随便推点

互联网医院智慧医院系统_互联网可访问的医院系统有哪些-程序员宅基地

文章浏览阅读8.5k次。什么是互联网医院?我们来看一下百度百科的定义“互联网医院系统”带有在线问诊、随访、慢病管理等功能,它有实体医院作强有力的支撑,线上方便病人,就是简单的问题不需要到医院,在网上就可以进行。可见在线问诊、随访、慢病管理是互联网医院的核心功能,下面我们来逐个分析一下在线问诊:一般是图文问诊、视频问诊、语音问诊、电话问诊几种问诊方式,多种方式方便医患在线沟通随访:医生可以对患者发起线上随访,患者可在线填写随访表单,后台可统计随访结果慢病管理:能对糖尿病、高血压等常见慢性病进行健康管理,医生可以随时查看病人_互联网可访问的医院系统有哪些

IOS开发 生成app图标_ios app图标生成-程序员宅基地

文章浏览阅读1.6k次。IOS开发,给app设置图标_ios app图标生成

[Python] Django 报错记录与解决_importerror: cannot import name 'iterable' from 'c-程序员宅基地

文章浏览阅读6.7k次,点赞3次,收藏17次。配置记录pycharm中打开Django项目并配置虚拟环境运行项目;将Django项目全局配置文件用统一的包进行管理;配置jinja2模板引擎;补充 Jinja2 模板引擎环境报错记录ImportError;You must set settings.ALLOWED_HOSTS if DEBUG is False;'cryptography' package is required;ImproperlyConfigured_importerror: cannot import name 'iterable' from 'collections

JSON文本互转及JsonNode,ObjectNode,ArrayNode简单理解-程序员宅基地

文章浏览阅读5.7k次。JSON文本互转及JsonNode,ObjectNode,ArrayNode简单理解``JsonNode是Jackson中为了处理JOSN文本的树模型(tree model)。可以将JSON文本转成JsonNode,也可以将JsonNode转成JOSN文本。。ObjectNode和ArrayNode都是JsonNode类的扩展,不同的是JsonNode是只读的,而。..._arraynode

测试理论-程序员宅基地

文章浏览阅读2.6w次,点赞10次,收藏71次。一、基本概念定义:软件测试是为了发现错误而执行程序的过程,“寻找错误”是测试的目的 使用人工或自动手段运行或测定某个系统的过程,其目的在于检验它是否满足规定的需求或是否弄清预期结果与实际结果之间的差别 软件测试是一种重要的软件质量保证活动,测试过程中的活动包括分析软件和运行软件,是在软件投入运行前,对软件需求分析、设计规格说明和编码的最终复审,是软_测试理论

精通数据库系列之入门-基础篇2-程序员宅基地

文章浏览阅读488次。数据库系统的产生和发展  众所周知,数据库系统并不是在计算机产生的同时就出现的,而是随着计算机技术的不断发展,在特定的历史时期、特定的需求环境下出现的。人类在1946年发明了世界上的第一台计算机到20世纪60年代这漫长的20年里,计算机操作系统还主要局限于文件的操作,同样,对数据的管理也主要是通过文件系统来实现。进行计算所需要的各种数据存放在各自的文件里面。当要使用这些数据的时候,将文件打开,读取

推荐文章

热门文章

相关标签