什么是内核对象

来源:互联网 发布:java项目设计流程 编辑:程序博客网 时间:2024/06/15 16:48
  1. /*
  2.     什么是内核对象
  3.     内核对象可通过调用各种各样的函数创建,这些函数需要传递一个与使用在内核
  4.     层的内核对象的类型不太一致的名称。比如,函数CreateFileMapping会告诉OS
  5.     去创建一个与区域对象(Section Object)相关的文件映射。每一个内核对象其实
  6.     是一个由内核定位的内存块且这个内存块只能被内核访问。内存块是一个数据
  7.     结构,其成员维护着内核对象的信息。其中一些成员对于所有类型的内核对象
  8.     都是相同的,如安全描述符(Security discriptor)和使用次数(Usage Count)
  9.     而其它的大部分是专属于指定类型的内核对象的,如进程对象会有进程ID,基础
  10.     优先级和退出码等属性,而文件对象会有字节偏移,共享模式和打开模式等。
  11.     因为内核对象只能被内核直接访问,所以应用程序不能直接在内存中定位内核对象
  12.     及改变其数据成员的值。MS故意做出这样的限制的主要目的是让内核对象对维护
  13.     一个常量值,而且OS在添加,删除及改变内核对象的时候不会影响到任何应用程序。
  14.     如果程序不能直接的访问内核对象,那我们的应用程序如何才能操作内核对象呢?
  15.     答案是MS给我们提供了一系列的定义良好的函数,通过这些函数我们的程序就可
  16.     以访问内核对象了。当你调用其中之一的函数去创建一个内核对象时,该函数会
  17.     给你返回一个标识内核对象的句柄。为了便于理解,可以把这个句柄想像成一个
  18.     不为人知的黑箱子,它可以被同程序进程内的任何线程使用。在32位的系统中,
  19.     此句柄是一个32位的值,在64位的系统中,此句柄是一个64位的值。你可以将此
  20.     句柄传给想调用的操作内核对象的函数,这样OS就能知道你要操作哪个内核对象。
  21.     为了使操作系统更加健壮,内核对象的句柄是与进程相关联的。即如果你通过一
  22.     种进程间通信的机制将内核对象的句柄传给了其它进程内的线程,那么被强制
  23.     使用非己内核对象的进程可能会失败,甚至发生错误。它们会在你的进程句柄表
  24.     中创建一个同索引号但不同的内核对象的引用。
  25.     使用次数:
  26.     内核对象属于内核,不属于进程。换言之,如果你的进程调用函数创建了一个
  27.     内核对象,当你的进程结束的时候,其创建的内核对象并不一定会被处理掉,
  28.     多数情况下会被处理掉,但也有特殊情况。比如你的进程创建的内核对象被其它
  29.     进程使用了,那么内核就不能处理掉该内核对象,直到没有任何的进程再使用
  30.     该内核对象时,其才会被删除。即需要记住的一点是,内核对象可生存在创建其
  31.     的进程之外。
  32.     内核通过内核对象的数据成员--使用次数能够知道当前有几个进程正在使用该
  33.     对象。每种类型的对象都有一相同的数据成员--使用次数。当内核对象首次被
  34.     创建出来的时候,其使用次数为1,当有其它进程得到该对象的访问权之后,其
  35.     使用次数增加,当使用该的进程结束时,使用次数会相应的减少。当一个内核对象
  36.     的使用次数变成0的时候,内核就会删除该对象。这样就可以保存当没有任何的
  37.     进程在使用一个内核对象时,该对象就不会再残留在内核中。
  38.     安全性:
  39.     安全描述符用于保存内核对象。一个安全描述符描述了对象的占据者,哪些组或
  40.     用户能够操作或访问该对象,哪些组或用户被拒绝访问。安全描述符通常用于
  41.     服务器程序中,但在Vista系统中,具有私有命名空间的客户端程序也通常使用
  42.     了安装描述符。
  43. */
  44. /*
  45.     几乎每一个创建内核对象的函数都需要一个指向SECURITY_ATTRIBUTE结构的指针
  46.     作为参数,比如:
  47. */
  48. HANDLE CreateFileMapping(
  49.                          HANDLE hFile,
  50.                          PSECURITY_ATTRIBUTES psa,
  51.                          DWORD flProtect,
  52.                          DWORD dwMaximumSizeHigh,
  53.                          DWORD dwMaximumSizeLow,
  54.                          PCTSTR pszName);
  55. /*
  56.     该参数在大部分的函数中会被设置为NULL,这样其所创建的内核对象就会使用基
  57.     于当前进程安全性的默认安全属性。当然,为了自己特殊的需求,我们可以声明
  58.     并初始化一个SECURITY_ATTRIBUTE结构,然后将其地址传递给调用函数。
  59.     SECURITY_ATTRIBUTE的结构如下:
  60. */
  61. typedef struct _SECURITY_ATTRIBUTES {
  62.                                     DWORD nLength;
  63.                                     LPVOID lpSecurityDescriptor;
  64.                                     BOOL bInheritHandle;
  65.                                     } SECURITY_ATTRIBUTES;
  66. /*
  67.     从上结构中可看出,SECURITY_ATTRIBUTES的主要成员即是lpSecurityDescriptor,
  68.     它可以描述任何类型的安全属性。如果你想创建一个具有访问限制性的内核对象,
  69.     你必须声明一个SECURITY_ATTRIBUTES并初始化如下:
  70. */
  71. SECURITY_ATTRIBUTES sa;
  72. sa.nLength = sizeof(sa);         // Used for versioning
  73. sa.lpSecurityDescriptor = pSD;   // Address of an initialized SD
  74. sa.bInheritHandle = FALSE;       // Discussed later
  75. HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
  76.                                         &sa,
  77.                                         PAGE_READWRITE,
  78.                                         0,
  79.                                         1024,
  80.                                         TEXT("MyFileMapping"));
  81. /*
  82.     如果你想获得已存在内核对象的访问权(不是创建新对象),你必须指定你想针对
  83.     该对象进行的操作。比如你想获得一个已存在的文件映射内核对象的访问权以便
  84.     能从其获取数据,你需要进行类似如下的操作:
  85. */
  86. HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ,
  87.                                       FALSE,
  88.                                       TEXT("MyFileMapping"));
  89. /*
  90.     传递的第一个参数FILE_MAP_READ意思是当我获取内核对象的访问权之后,我想
  91.     从其内读取一些数据。应该函数在返回句柄之前首先会进行安全性检查。
  92.     如果调用者获取了对象的访问权,该函数会返回一个可用的句柄,如果调用者
  93.     被拒绝了,该函数会返回NULL,此时GetLastError会返回5(ERROR_ACCESS_DENIED)
  94.     不要忘记,如果应该句柄被用于一个需要非FILE_MAP_READ的API函数,“拒绝访问”
  95.     同样也会发生,因为操作类型不符合。
  96. */
  97. /*
  98.     需要注意几点:
  99.     1:新版本的Windows操作系统总会具有一些旧版本的Windows操作系统所不具备
  100.        的特性,所以在涉及到安全性操作的时候,最好能知道自己的操作需要被操作
  101.        对象的哪些安全属性。比如当用户想通过函数RegOpenKeyEx读取注册表值的
  102.        时候,权限传递为KEY_QUERY_VALUE是比较合适的。但许多以前针对2000等旧
  103.        系统编写的程序在读取注册表时,如果开发者没有关心其所进行的操作仅仅
  104.        是读取,而是直接使用了KEY_ALL_ACCESS 安全属性,这可能会有潜在的问题。
  105.        因为一些注册表的子项如HKLM在非管理员权限下是只能读取而不能被写入的。
  106.        传递KEY_ALL_ACCESS就意味着也能写入,这样的程序运行在Vista上的时候
  107.        就会失败并导致不可预知的错误。
  108.    2:对象类别的区分
  109.       Windows系统中有各种类型的对象,如何才能知道它是不是内核对象?有一点
  110.       很明确,即几乎所有创建内核对象的函数都需要一个SECURITY_ATTRIBUTES指针,
  111.       而非内核对象的创建函数都不需要SECURITY_ATTRIBUTES指针。通过对象的创建
  112.       函数,我们基本上就能明确创建的对象是否为一个内核对象。
  113. */
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怀孕五个月胎位不正怎么办 33周了胎位不正怎么办 足月胎儿不足5斤怎么办 绒癌观察期怀孕怎么办 宝宝囱门闭合晚怎么办 慢性硬脑膜下血肿复发怎么办 佝偻病导致囟门晚闭怎么办 儿童液体补多了怎么办 脑脊液鼻漏3年了怎么办 结石掉到膀胱里怎么办 肾结石引起的腰疼怎么办 肾结石小但很疼怎么办 狗狗得了尿结石怎么办 生理期第四天必须游泳怎么办 碎石后吐的厉害怎么办 白细胞高红细胞高血尿怎么办? 早期肾癌术后复发该怎么办 肾结石因运动引起尿血怎么办 宝宝大便镜检阳性潜血怎么办 尿不尽刺痛带血怎么办 狗狗拉肚子拉血怎么办 肾血肿怎么办才吸收快 体检尿蛋白高3怎么办 肾炎会引起脸肿怎么办 12小孩尿蛋白3是怎么办 肝癌介入手术后肝功能不好怎么办 屁多且臭便秘怎么办 肝癌术1年后复发怎么办 怀孕便秘怎么办或大便太干拉不出 肠鸣便秘怎么办多尿 奥司他韦过量怎么办 憋的时间长尿痛怎么办 手过敏了怎么办最简单 肾结石不痛但是有血尿怎么办 儿童医院血液科挂不到号怎么办 搬完重物手抖怎么办 弯腰搬重物腰疼怎么办 搬了重物后腰疼怎么办 例假不走公务员体检血尿怎么办 憋尿久了尿不出来怎么办 憋尿引起的总有尿意怎么办