什么是内核对象
来源:互联网 发布:java项目设计流程 编辑:程序博客网 时间:2024/06/15 16:48
- /*
- 什么是内核对象
- 内核对象可通过调用各种各样的函数创建,这些函数需要传递一个与使用在内核
- 层的内核对象的类型不太一致的名称。比如,函数CreateFileMapping会告诉OS
- 去创建一个与区域对象(Section Object)相关的文件映射。每一个内核对象其实
- 是一个由内核定位的内存块且这个内存块只能被内核访问。内存块是一个数据
- 结构,其成员维护着内核对象的信息。其中一些成员对于所有类型的内核对象
- 都是相同的,如安全描述符(Security discriptor)和使用次数(Usage Count)
- 而其它的大部分是专属于指定类型的内核对象的,如进程对象会有进程ID,基础
- 优先级和退出码等属性,而文件对象会有字节偏移,共享模式和打开模式等。
- 因为内核对象只能被内核直接访问,所以应用程序不能直接在内存中定位内核对象
- 及改变其数据成员的值。MS故意做出这样的限制的主要目的是让内核对象对维护
- 一个常量值,而且OS在添加,删除及改变内核对象的时候不会影响到任何应用程序。
- 如果程序不能直接的访问内核对象,那我们的应用程序如何才能操作内核对象呢?
- 答案是MS给我们提供了一系列的定义良好的函数,通过这些函数我们的程序就可
- 以访问内核对象了。当你调用其中之一的函数去创建一个内核对象时,该函数会
- 给你返回一个标识内核对象的句柄。为了便于理解,可以把这个句柄想像成一个
- 不为人知的黑箱子,它可以被同程序进程内的任何线程使用。在32位的系统中,
- 此句柄是一个32位的值,在64位的系统中,此句柄是一个64位的值。你可以将此
- 句柄传给想调用的操作内核对象的函数,这样OS就能知道你要操作哪个内核对象。
- 为了使操作系统更加健壮,内核对象的句柄是与进程相关联的。即如果你通过一
- 种进程间通信的机制将内核对象的句柄传给了其它进程内的线程,那么被强制
- 使用非己内核对象的进程可能会失败,甚至发生错误。它们会在你的进程句柄表
- 中创建一个同索引号但不同的内核对象的引用。
- 使用次数:
- 内核对象属于内核,不属于进程。换言之,如果你的进程调用函数创建了一个
- 内核对象,当你的进程结束的时候,其创建的内核对象并不一定会被处理掉,
- 多数情况下会被处理掉,但也有特殊情况。比如你的进程创建的内核对象被其它
- 进程使用了,那么内核就不能处理掉该内核对象,直到没有任何的进程再使用
- 该内核对象时,其才会被删除。即需要记住的一点是,内核对象可生存在创建其
- 的进程之外。
- 内核通过内核对象的数据成员--使用次数能够知道当前有几个进程正在使用该
- 对象。每种类型的对象都有一相同的数据成员--使用次数。当内核对象首次被
- 创建出来的时候,其使用次数为1,当有其它进程得到该对象的访问权之后,其
- 使用次数增加,当使用该的进程结束时,使用次数会相应的减少。当一个内核对象
- 的使用次数变成0的时候,内核就会删除该对象。这样就可以保存当没有任何的
- 进程在使用一个内核对象时,该对象就不会再残留在内核中。
- 安全性:
- 安全描述符用于保存内核对象。一个安全描述符描述了对象的占据者,哪些组或
- 用户能够操作或访问该对象,哪些组或用户被拒绝访问。安全描述符通常用于
- 服务器程序中,但在Vista系统中,具有私有命名空间的客户端程序也通常使用
- 了安装描述符。
- */
- /*
- 几乎每一个创建内核对象的函数都需要一个指向SECURITY_ATTRIBUTE结构的指针
- 作为参数,比如:
- */
- HANDLE CreateFileMapping(
- HANDLE hFile,
- PSECURITY_ATTRIBUTES psa,
- DWORD flProtect,
- DWORD dwMaximumSizeHigh,
- DWORD dwMaximumSizeLow,
- PCTSTR pszName);
- /*
- 该参数在大部分的函数中会被设置为NULL,这样其所创建的内核对象就会使用基
- 于当前进程安全性的默认安全属性。当然,为了自己特殊的需求,我们可以声明
- 并初始化一个SECURITY_ATTRIBUTE结构,然后将其地址传递给调用函数。
- SECURITY_ATTRIBUTE的结构如下:
- */
- typedef struct _SECURITY_ATTRIBUTES {
- DWORD nLength;
- LPVOID lpSecurityDescriptor;
- BOOL bInheritHandle;
- } SECURITY_ATTRIBUTES;
- /*
- 从上结构中可看出,SECURITY_ATTRIBUTES的主要成员即是lpSecurityDescriptor,
- 它可以描述任何类型的安全属性。如果你想创建一个具有访问限制性的内核对象,
- 你必须声明一个SECURITY_ATTRIBUTES并初始化如下:
- */
- SECURITY_ATTRIBUTES sa;
- sa.nLength = sizeof(sa); // Used for versioning
- sa.lpSecurityDescriptor = pSD; // Address of an initialized SD
- sa.bInheritHandle = FALSE; // Discussed later
- HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
- &sa,
- PAGE_READWRITE,
- 0,
- 1024,
- TEXT("MyFileMapping"));
- /*
- 如果你想获得已存在内核对象的访问权(不是创建新对象),你必须指定你想针对
- 该对象进行的操作。比如你想获得一个已存在的文件映射内核对象的访问权以便
- 能从其获取数据,你需要进行类似如下的操作:
- */
- HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ,
- FALSE,
- TEXT("MyFileMapping"));
- /*
- 传递的第一个参数FILE_MAP_READ意思是当我获取内核对象的访问权之后,我想
- 从其内读取一些数据。应该函数在返回句柄之前首先会进行安全性检查。
- 如果调用者获取了对象的访问权,该函数会返回一个可用的句柄,如果调用者
- 被拒绝了,该函数会返回NULL,此时GetLastError会返回5(ERROR_ACCESS_DENIED)
- 不要忘记,如果应该句柄被用于一个需要非FILE_MAP_READ的API函数,“拒绝访问”
- 同样也会发生,因为操作类型不符合。
- */
- /*
- 需要注意几点:
- 1:新版本的Windows操作系统总会具有一些旧版本的Windows操作系统所不具备
- 的特性,所以在涉及到安全性操作的时候,最好能知道自己的操作需要被操作
- 对象的哪些安全属性。比如当用户想通过函数RegOpenKeyEx读取注册表值的
- 时候,权限传递为KEY_QUERY_VALUE是比较合适的。但许多以前针对2000等旧
- 系统编写的程序在读取注册表时,如果开发者没有关心其所进行的操作仅仅
- 是读取,而是直接使用了KEY_ALL_ACCESS 安全属性,这可能会有潜在的问题。
- 因为一些注册表的子项如HKLM在非管理员权限下是只能读取而不能被写入的。
- 传递KEY_ALL_ACCESS就意味着也能写入,这样的程序运行在Vista上的时候
- 就会失败并导致不可预知的错误。
- 2:对象类别的区分
- Windows系统中有各种类型的对象,如何才能知道它是不是内核对象?有一点
- 很明确,即几乎所有创建内核对象的函数都需要一个SECURITY_ATTRIBUTES指针,
- 而非内核对象的创建函数都不需要SECURITY_ATTRIBUTES指针。通过对象的创建
- 函数,我们基本上就能明确创建的对象是否为一个内核对象。
- */
- 什么是内核对象
- 什么是内核对象
- 什么是内核(kernel)对象?
- 3.1 什么是内核对象
- 3.1 什么是内核对象
- Windows-核心编程-03-什么是内核对象
- 什么是内核
- 什么是内核
- 什么是内核
- 什么是内核
- 什么是内核?
- WINDOWS核心编程之什么是内核对象(一)
- WINDOWS核心编程之什么是内核对象(二)
- WINDOWS核心编程之什么是内核对象(三)
- WINDOWS核心编程之什么是内核对象(一)
- WINDOWS核心编程之什么是内核对象(二)
- WINDOWS核心编程之什么是内核对象(三)
- 什么是类,什么是对象?
- lvm代码分析(五)
- 无聊的日子
- 文件操作
- proxool配置
- 成功实施SOA三步走
- 什么是内核对象
- 简单变长内存池实现的实现
- VS2008 .NET 3.5介绍
- vs2005 中 inc 和 lib
- linux学习笔记
- stream input的含义
- 安装配置Lustre集群文件系统
- CppUnit测试框架入门
- 开博