【Windows 操作系统】Windows 进程的内核对象句柄表
总结:
1、句柄就是进程句柄表中的索引。
2、句柄是对进程范围内一个内核对象地址的引用,一个进程的句柄传给另一个进程是无效的。一个内核对象可用有多个句柄。
Windows之所以要设立句柄,根本上源于内存管理机制的问题,即虚拟地址。简而言之数据的地址需要变动,变动以后就需要有人来记录、管理变动,因此系统用句柄来记载数据地址的变更。
当一个进程被初始化时,系统要为它分配一个句柄表。该句柄表只用于内核对象 ,不用于用户对象或 GDI 对象。
。第一个句柄索引为4,第二个是8。
创建内核对象
当进程初次被初始化时,它的句柄表是空的。然后,当进程中的线程调用创建内核对象的函数时,比如 CreateFileMapping,内核就为该对象分配一个内存块,并对它初始化。这时,内核对进程的句柄表进行扫描,找出一个空项。由于表 3 - 1 中的句柄表是空的,内核便找到索引 4位置上的结构并对它进行初始化。该指针成员将被设置为内核对象的数据结构的内存地址,访问屏蔽设置为全部访问权,同时,各个标志也作了设置。
下面列出了用于创建内核对象的一些函数(不是个完整的列表):
HANDLE CreateThread(
PSECURITY_ATTRIBUTE psa,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam,
DWORD dwCreationFlags,
PDWORD pdwThreadId); HANDLE CreateFile(
PCTSTR pszFileNAme,
DWORD dwDesiredAccess,
DWORD dwShareMode,
PSECURITY_ATTRIBUTES psa,
DWORD dwCreationDistribution,
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,8 等。
每当调用一个将内核对象句柄接受为参数的函数时,就要传递由一个 Create*&函数返回的值。从内部来说,该函数要查看进程的句柄表,以获取要生成的内核对象的地址,然后按定义得很好的方式来生成该对象的数据结构。
如果传递了一个无效索引(句柄),该函数便返回失败,而 GetLastError 则返回 6(ERROR_INVALID_HANDLE)。由于句柄值实际上是放入进程句柄表的索引,因此这些句柄是与进程相关的,并且不能由其他进程成功地使用。
如果调用一个函数以便创建内核对象,但是调用失败了,那么返回的句柄值通常是 0(NULL)。发生这种情况是因为系统的内存非常短缺,或者遇到了安全方面的问题。不过有少数函数在运行失败时返回的句柄值是-1(INVALID_HANDLE_VALUE)。例如,如果 CreateFile 未能打开指定的文件,那么它将返回 INVALID_HANDLE_VALUE,而不是返回 NULL。当查看创建内核对象的函数返回值时,必须格外小心。特别要注意的是,只有当调用 CreateFile 函数时,才能将该值与 INVALID_HANDLE_VALUE 进行比较。下面的代码是不正确的:
HANDLE hMutex = CreateMutex(...);
if (hMutex == INVALID_HANDLE_VALUE) {
//这段代码不会执行,因为CreateMutex调用失败的时候返回的是NULL
}
同样的,下面的代码也不正确:
HANDLE hFile = CreateFile(...);
if (hFIle == NULL) {
//这段代码不会执行,因为CreateFile调用失败的时候返回的是INVALID_HANDLE_VALUE(-1)
}
关闭内核对象
无论怎样创建内核对象,都要向系统指明将通过调用 C l o s e H a n d l e 来结束对该对象的操作:
BOOL CloseHandle(HANDLE hobj);
如果该句柄是有效的,那么系统就可以获得内核对象的数据结构的地址,并可确定该结构中的使用计数的数据成员。如果使用计数是 0,该内核便从内存中撤消该内核对象。
如果将一个无效句柄传递给 CloseHandle,将会出现两种情况之一。如果进程运行正常,CloseHandle 返回 FALSE,而 GetLastError 则返回 ERROR_INVALID_HANDLE。如果进程正在排除错误,系统将通知调试程序,以便能排除它的错误。
在 CloseHandle 返回之前,它会清除进程的句柄表中的项目,该句柄现在对你的进程已经无效,不应该试图使用它。无论内核对象是否已经撤消,都会发生清除操作。当调用 CloseHandle 函数之后,将不再拥有对内核对象的访问权,不过,如果该对象的使用计数没有递减为 0,那么该对象尚未被撤消。这没有问题,它只是意味着一个或多个其他进程正在使用该对象。当其他进程停止使用该对象时(通过调用 CloseHandle),该对象将被撤消。
假如忘记调用 CloseHandle 函数,那么会不会出现内存泄漏呢?答案是可能的,但是也不一定。在进程运行时,进程有可能泄漏资源(如内核对象)。但是,当进程终止运行时,操作系统能够确保该进程使用的任何资源或全部资源均被释放,这是有保证的。对于内核对象来说,系统将执行下列操作:当进程终止运行时,系统会自动扫描进程的句柄表。如果该表拥有任何无效项目(即在终止进程运行前没有关闭的对象),系统将关闭这些对象句柄。如果这些对象中的任何对象的使用计数降为 0,那么内核便撤消该对象。
因此,应用程序在运行时有可能泄漏内核对象,但是当进程终止运行时,系统将能确保所有内容均被正确地清除。另外,这个情况适用于所有对象、资源和内存块,也就是说,当进程终止运行时,系统将保证进程不会留下任何对象。
作者:Akkuman
链接:https://ld246.com/article/1518194894673
来源:链滴
协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/
【Windows 操作系统】Windows 进程的内核对象句柄表的更多相关文章
- Windows进程的内核对象句柄表
当一个进程被初始化时,系统要为它分配一个句柄表.该句柄表只用于内核对象 ,不用于用户对象或GDI对象. 创建内核对象 当进程初次被初始化时,它的句柄表是空的.然后,当进程中的线程调用创建内核对象的函数 ...
- windows内核对象句柄
内核对象用于管理进程.线程和文件等诸多种类的大量资源,每一个内核对象都只是一个句内存快,它由操作系统内核分配,并只能右操作系统内核访问.这个内存块是一个数据结构,其维护着与对象相关的信息,其中少数成员 ...
- 【Windows 操作系统】 内核对象|句柄
内核对象简介 内核对象就是 一些数据结构该结构用来描述存储内核中的一个内存块中的数据信息. 内存块是一种数据结构,其中的数据成员负责维护该对象的相应信息,这个数据结构以及其中的数据成员只能由内核访 ...
- Windows API学习---线程与内核对象的同步
前言 若干种内核对象,包括进程,线程和作业.可以将所有这些内核对象用于同步目的.对于线程同步来说,这些内核对象中的每种对象都可以说是处于已通知或未通知的状态之中.这种状态的切换是由Microsoft为 ...
- Windows核心编程笔记之内核对象
0x01 子进程继承父进程内核对象句柄 父进程 #include <Windows.h> #include <iostream> #include <strsafe.h& ...
- 内核对象&句柄&泄漏&检测
今天看到这个问题如何评价王垠的 <讨厌的 C# IDisposable 接口>? - 王垠(人物),答案被歪到windows 内核对象和句柄,答案中谈的太浅显而且有误.翻出陈年老文章(此文 ...
- 内核对象&句柄
目录 1 内核对象的概念 2 内核对象的使用计数 3 句柄 4 句柄表 项目工程代码中设计句柄的使用,一时不知句柄是何物,通过查阅自学之后,对句柄及其使用有一个初步的了解.分享出来,算是抛砖引玉吧 ...
- 内存块是一种数据结构,内核对象&句柄
内核对象&句柄 目录 1 内核对象的概念 2 内核对象的使用计数 3 句柄 4 句柄表 项目工程代码中设计句柄的使用,一时不知句柄是何物,通过查阅自学之后,对句柄及其使用有一个初步的了解. ...
- 【windows 操作系统】进程控制块(PCB)
转载地址:https://blog.csdn.net/qq_38499859/article/details/80057427一.目录文章目录 操作系统3 ----进程控制块(PCB)详解 ...
随机推荐
- golang中使用zap日志库
1. 快速使用 package main import ( "go.uber.org/zap" "time" ) func main() { // 1. sug ...
- sed 模式空间 保持空间
sed之所以能以行为单位的编辑或修改文本,其原因在于它使用了两个空间:一个是活动的"模式空间(pattern space)",另一个是起辅助作用的"保持空间(hold s ...
- Web安全防护(二)
点击劫持 点击劫持,也称UI覆盖攻击 1.1 iframe覆盖攻击 黑客创建一个网页,用iframe包含了目标网站,并且把它隐藏起来.做一个伪装的页面或图片盖上去,且按钮与目标网站一致,诱导用户去点击 ...
- MySQL开发篇,存储引擎的选择真的很重要吗?
前言 谁说MySQL查询千万级别的数据很拉跨?我今天就要好好的和你拉拉家常,畅谈到深夜,一起过除夕!这篇文章也是年前的最后一篇,希望能带给大家些许收获,不知不觉查找文档和参考实体书籍就写了这么多,自己 ...
- Azure AD Domain Service(一)将 Azure VM 实例添加到域服务里
一,引言 有网友提到实际项目中如何将 Azuer VM 实例加入到 Azure AD 域,那我们今天就带着整个问题开始今天的分析!首先我们得了解什么是 Azure AD 域服务,Azure AD 域服 ...
- Linux 常见文件管理命令
Linux文件系统 根目录:/ 从根目录开始,下面有一堆小目录 root:根用户的目录 bin:可执行文件命令 etc:配置文件 var:日志 lib:安装包或头文件,库文件 home:所有用户的家目 ...
- ApacheCN Vue 译文集 20211115 更新
使用 GraphQL 构建 VueJS 应用 零.前言 一.数据绑定.事件和计算属性 二.组件.混合器和功能组件 三.设置我们的聊天应用--AWS Amplify 环境和 GraphQL 四.创建自定 ...
- asp.net core 中的各种路径
1.获取完整网址URL 方法一:先引用"using Microsoft.AspNetCore.Http.Extensions;",然后直接用"Request.GetDis ...
- Java GUI界面补充总结(不定期补充)
一.Java中如何设置各类组件透明 感谢原文:https://kslsi.iteye.com/blog/2096608 补充:Frame透明:AWTUtilities.setWindowOpacity ...
- Android文件的权限概念
//通过context对象获取一个私有目录的文件读取流 /data/data/packagename/files/userinfoi.txt FileInputStream fileInputS ...