1.每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核访问。这个内存块是一个数据结构,其成员维护着与对象相关的信息。

2.调用一个会创建内核对象的函数后,函数会返回一个句柄,它标识了所创建的对象。在32位windows进程中,句柄是一个32位的值,在64位windows进程中,则是一个64位的值。

3.为了增强操作系统的可靠性,这些句柄值是与进程相关的,不可以直接跨进程使用。

4.内核对象的所有者是操作系统内核,而非进程,在进程内创建的内核对象在进程终止时不一定会被销毁。大多数情况下是会被销毁的,但是假如另一个进程正在使用我们的进程创建的内核对象,那么在其他进程停止使用它之前是不会被销毁的。

5.操作系统的内核知道当前有多少个进程正在使用一个特定的内核对象,因为每个对象都包含一个使用计数。使用计数是所有内核对象类型都有的一个数据成员。初次创建 一个对象的时候,使用计数被设为1,另一个进程获得对现有内核对象的访问后,使用计数就会递增。进程终止运行后,操作系统内核将自动递减此进程仍然打开的所有内核对象的使用计数。一旦使用计数变成0,操作系统内核就会销毁该对象。可以保证系统中不存在没有被任何进程引用的内核对象。

6.内核对象可以用一个安全描述符来保护。安全描述符描述了谁拥有对象,哪些组和用户被允许/拒绝访问或使用此对象。

7.一个进程在初始化时,系统将为它分配一个句柄表。这个句柄表仅供内核对象使用。

8.系统用索引来表示内核对象的信息保存在进程句柄表中的具体位置,要得到实际的索引值,句柄值实际应该除以4(忽略Windows操作系统内部使用的最后两位)。

9.CloseHandle() 会先检查句柄是否有效,如果有效,系统就将获得内核对象的数据结构的地址,并将结构中的“使用计数”成员递减,如果变成0,则内核对象将被销毁,并从内存中移出去。

10.在CloseHandle() 函数返回之前,它会清除进程句柄表中对应的记录项,无论内核对象当前是否销毁,这个清除过程都会发生。

11.三种不同的机制允许进程共享内核对象:使用对象句柄继承,为对象命名,复制对象句柄。

使用对象句柄继承

1.只有在进程之间有一个父子关系的时候,才可以使用对象句柄继承。句柄表中的每个记录项都有一个指明句柄是否可以继承的标志位,如果PSECURUTY_ATTRIBUTES传入的参数时NULL,则返回的句柄是不可继承的,这个标志位为0,将bInheritHandle成员设置为TRUE,则导致这个标志位被设为1。

2.例如在CreateProcess函数的bInheritHandles参数的值是TRUE,系统会遍历父进程的句柄表,对它的每一个记录项进行检查,凡是包含一个有效的"可继承的句柄"项,都会被完整地复制到子进程的句柄表。而且在子进程的句柄表中,复制项的位置与它在父进程句柄表中的位置是完全一样的。也意味着:在父进程和子进程中,对一个内核对象进行标识的句柄值是完全一样的。同时系统还会递增内核对象的使用计数。同理,孙进程也会继承这个内核对象句柄。

3.对象句柄的继承只会发生在生成子进程的时候,假如父进程后来又创建了新的内核对象,那么子进程是不会继承这些新的句柄。

4.子进程并不知道自己继承了任何句柄。

5. SetHandleInformation()函数可以用来改变内核对象句柄的继承标志,GetHandleInformation()可以获得指定句柄的状态标志。

为对象命名

1.所有对象都共享同一个命名空间,即使它们类型并不相同。

2.如果进程A中已经创建了一个命名对象(即使是不可继承的),那么在进程B中以同样的名字来创建命名对象时,系统会首先查看是否存在相同名称的内核对象,如果确实存在,内核接着检查对象的类型,如果类型不匹配就会返回NULL。如果匹配则系统接着执行一次安全检查,严重调用者是否拥有对该对象的完全访问权限,如果拥有则系统会在进程B的句柄表中查找一个空白记录项,并将其初始化为指向现有的内核对象。如果被拒绝访问,则失败。

    // Process A
HANDLE hMutexA = CreateMutex(NULL,false,_T("MyMutex")); // Process B
HANDLE hMutexB = CreateMutex(NULL, false, _T("MyMutex"));

3.用于创建内核对象的函数(比如CreateSemaphore)总是返回具有完全访问权限的句柄。如果想限制一个句柄的访问权限,可以使用这些函数的扩展版本(*ex)。

4.由于在进程B的句柄表中,用一个新的记录项来引用了这个对象,所以这个互斥量对象的使用计数会被增加。

5。进程B创建内核对象时,如果已经存在,则传递的安全属性和其他参数会被忽略。

6.调用Create*函数和调用Open*函数的主要区别在于,如果对象不存在,Create*会创建,Open*只是调用失败。

7.终端服务的情况和前面描述的稍微有所区别。正在运行终端服务的计算机中,有多个用于内核对象的命名空间。其中一个时全局命名空间,所有客户端都能访问的内核对象要放在这个命名空间中。这个命名空间主要由服务使用。此外,每个客户端会话都有一个自己的命名空间,这样即使对象的名称相同也会不互相干扰。并非只有服务器才会遇到这种情况,因为Remote Desktop和快速用户切换特性也是利用终端服务会话来实现的。

8.在没有任何用户登陆的时候,服务会在第一个会话(Session 0)中启动,这个会话不是交互式的。和以前的版本不同,在Windows Vista中,只要用户登陆,应用程序就会在一个新的会话(与Session 0不同的一个会话)中启动。所以.任何对象想要和用户应用程序共享,都必须在全局命名空间中创建它。

9.如果必须知道我们的进程在哪个Terminal Services会话中运行,可以借助于ProcessIdToSessionId函数。

10.一个服务的命名内核对象始终位于全局命名空间内。默认情况下,在终端服务中,应用程序自己的命名内核对象在会话的命名空间内。不过我们可以在其名称前加上“Global\”前缀强制把一个命名对象放入全局命名空间。或者在名称前加上“Local\”前缀把内核对象放入当前会话的命名空间中。

HANDLE hGlobal = CreateEvent(NULL,FALSE,FALSE,_T("Global\\MyName"));
HANDLE hLocal = CreateEvent(NULL, FALSE, FALSE, _T("Local\\MyName"));

11.Microsoft认为Global和Local是保留关键字,所以除非为了强制一个特定的命名空间,否则不应在对象名称中使用它们。Session也是保留关键字,我们可以使用Session\<当前会话ID>\,但是不能使用另一个会话中的名称和Session前缀来新建一个对象,这样会导致函数调用失败。

12.所有保留关键字都是区分大小写的。

复制对象句柄

1.DuplicateHandle函数获得一个进程的句柄表中的一个记录项,然后在另一个进程的句柄表中创建这个记录项的一个副本。其第一个和第三个参数必须是进程内核对象。第二个参数是指向任何类型的内核对象的一个句柄。但是它的句柄值一定不能与调用DuplicateHandle函数的那个进程相关。

DuplicateHandle(
_In_ HANDLE hSourceProcessHandle,
_In_ HANDLE hSourceHandle,
_In_ HANDLE hTargetProcessHandle,
_Outptr_ LPHANDLE lpTargetHandle,
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwOptions
);

2.进程中永远不要关闭为另外一个进程复制出来的句柄。

Windows Internals 笔记——内核对象的更多相关文章

  1. Windows核心编程&内核对象

    1. 一个进程在初始化时,系统将会他分配一个空的句柄表,这个句柄表仅供内核对象使用,不供用户对象和GDI对象使用.进程在首次 初始化时,该句柄表为空.句柄表是一个由数据结构组成的数组,包含一个内核对象 ...

  2. Windows Internals 笔记——关联性

    1.默认情况下,Windows Vista在给线程分配处理器时,使用软关联.意思是如果其他因素都一样,系统将使线程在上一次运行的处理器上运行.让线程始终在同一个处理器上运行有助于重用仍在处理器高速缓存 ...

  3. Windows Internals 笔记——线程调度

    1.线程内核对象中的CONTEXT反应了线程上一次执行时CPU寄存器的状态.大约每隔20ms,Windows都会查看所有当前存在的线程内核对象.Windows在可调度的线程内核对象中选择一个,并将上次 ...

  4. Windows Internals 笔记——线程

    1.进程有两个组成部分,一个进程内核对象和一个地址空间.线程也有两个组成部分: 一个是线程的内核对象,操作系统用它管理线程.系统还用内核对象来存放线程统计信息的地方. 一个线程栈,用于维护线程执行时所 ...

  5. Windows Internals 笔记——作业

    1.Windows提供了一个作业内核对象,它允许我们将进程组合在一起并创建一个“沙箱”来限制进程能够做什么.创建只包含一个进程的作业同样非常有用,因为这样可以对进程施加平时不能施加的限制. 2.如果进 ...

  6. Windows Internals 笔记——CreateProcess

    1.一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.然后系统为新进程的主线程创建一个线程内核对象(使其计数为1). 2.CreateProcess在进程完全初 ...

  7. Windows Internals 笔记——进程

    1.一般将进程定义成一个正在运行的程序的一个实例,由以下两部分构成: 一个内核对象,操作系统用它来管理进程,内核对象也是系统保存进程统计信息的地方. 一个地址空间,其中包含所有可执行文件或DLL模块的 ...

  8. Windows进程的内核对象句柄表

    当一个进程被初始化时,系统要为它分配一个句柄表.该句柄表只用于内核对象 ,不用于用户对象或GDI对象. 创建内核对象 当进程初次被初始化时,它的句柄表是空的.然后,当进程中的线程调用创建内核对象的函数 ...

  9. windows编程之内核对象

          学好windows编程,理解内核对象还是至关重要的(●'◡'●).闲话不多说,下面先来了解一下关于内核对象的知识:       内核对象(kernel object):内核对象是用于管理进 ...

随机推荐

  1. 接口请求,上传byte数组byte[]数据异常,负数变正数/负数变63

    一.背景 最近项目中有个需求,就是需要把一个byte[]数组上传到服务端.但是我发现发送的byte数组和服务端接收的数组不一样,所有的正数在传递时正确,数组长度也没变化,但是负数变成了63或者负数全部 ...

  2. css实现多行文本溢出显示省略号(…)

    WebKit浏览器或移动端的页面在WebKit浏览器或移动端(绝大部分是WebKit内核的浏览器)的页面实现比较简单,可以直接使用WebKit的CSS扩展属性(WebKit是私有属性)-webkit- ...

  3. Lodop打印控件传入css样式、看是否传入正确样式

    Lodop中可以传入页面存在的css样式,也可以是拼接后的新样式,例如本博客的其他博文:Lodop打印如何隐藏table某一列 需要打印的页面,样式不一定都是行内样式,style样式单独写在页面上,或 ...

  4. 数据降维之多维缩放MDS(Multiple Dimensional Scaling)

    网上看到关于数据降维的文章不少,介绍MDS的却极少,遂决定写一写. 考虑一个这样的问题.我们有n个样本,每个样本维度为m.我们的目标是用不同的新的k维向量(k<<m)替代原来的n个m维向量 ...

  5. 【论文阅读】Sequence to Sequence Learning with Neural Network

    Sequence to Sequence Learning with NN <基于神经网络的序列到序列学习>原文google scholar下载. @author: Ilya Sutske ...

  6. Django admin组件源码流程

    admin 组件 Django 自带的用户后台组件 用于用户便携的操作 admin 组件核心 启动 注册 设计url 启动核心代码 每个app 通过 apps.py 扫描 admin.py 文件 并执 ...

  7. Codeforces 629D Babaei and Birthday Cakes DP+线段树

    题目:http://codeforces.com/contest/629/problem/D 题意:有n个蛋糕要叠起来,能叠起来的条件是蛋糕的下标比前面的大并且体积也比前面的大,问能叠成的最大体积 思 ...

  8. C++ bitset 常用函数及运算符

    C++ bitset--高端压位卡常题必备STL 以下内容翻译自cplusplus.com,极大地锻炼了我的英语能力. bitset存储二进制数位. bitset就像一个bool类型的数组一样,但是有 ...

  9. JavaScript继承的几种实现

    0 什么是继承 继承就是获得存在对象已有的属性和方法的一种方式. [2019.4.26 更新]今日又重新学习了一下JS的继承,在这里整理一下以前的笔记并补充一些新的感悟. 1 JS中继承的几种实现方法 ...

  10. 我眼中的支持向量机(SVM)

    看吴恩达支持向量机的学习视频,看了好几遍,才有一点的理解,梳理一下相关知识. (1)优化目标: 支持向量机也是属于监督学习算法,先从优化目标开始.   优化目标是从Logistics regressi ...