Windows学习(010)--内核对象(一)

来源:互联网 发布:java api中文文档 编辑:程序博客网 时间:2024/06/15 02:54

内核对象概述

  • Windows操作系统分为Ring3和Ring0层
  • Ring3层是全开放的, 无监管的
  • Ring0层是有监管的
    • 是操作系统以及软件正在运行的地方
    • 在软件运行的时候, 我们正真的操作都是在Ring0发生的
    • 可通过WinAPI向Ring0层发送请求
    • 当Ring0层检测到这是一个合理的请求时,内核对象会被Ring0层进行改变
  • 通过句柄可以操作Ring0层指定的内核对象
    • 但是句柄不代表Ring0层的某个具体的内核对象
    • 句柄的值是不透明的, 无人知道它代表了什么意思
    • 句柄是属于当前进程的

使用计数

  • 每一个内核对象中, 都会有一个使用计数
  • 内核对象是属于操作系统的
  • 内核对象属于全局的,不同进程可以使用同一个内核对象
  • 但是进程不能决定任何一个内核对象的生死
  • 内核对象的生死却是由操作系统来决定

    • 当内核对象没有意义的时候, 操作系统会清理内核对象以节约资源
    • 但是Ring0和Ring3又无法交互
    • 所以使用计数出现了
    • 使用计数会在使用的时候+1, 在不使用的时候-1
    • 当使用计数为0时, 操作系统会对内核对象进行回收
    • 回收不是实时的, 是当系统空闲的时候, 优先来清理的
  • 使用计数使得内核对象可以被多个进程所拥有, 并且能正确的释放

句柄表以及句柄的本质

  • 先前也说过,我们可以通过句柄来操作内核对象,但句柄不代表内核对象本身,当一个句柄走出了一个进程,就毫无意义.
  • 句柄是属于进程的,它存在于进程的句柄表中.通常创建一个内核对象的情景是,先在ring0中创建了一个内核对象,然后在进程句柄表中,找一个空白的索引的位置创建一个句柄,然后由此句柄中一个指针指向这个内核对象

句柄表存在的意义

  • 在CloseHandle的时候,它会去进程的句柄表中找到索引对应的内核对象,找到后给内核对象发送一个使用计数递减的指令
  • 当我们进程中的句柄在进程将要结束时,未被Closehandle,这样就回造成内核对象泄露.此时,句柄表就有了作用,它会根据其中的值,挨个CloseHandle

Signal状态

  • 有Signal状态的内核对象
    • 进程内核对象
    • 线程内核对象
      • 进程和线程内核对象在初始化的时候, Signal为FALSE
      • 等到它们运行完成, Signal为TRUE
      • 进程和线程内核对象就进入可受信(可接受信号)状态
      • 进程和线程内核对象的Signal状态是系统来控制的
    • 标准输入输出流对象
    • 事件
    • 互斥体
    • 信号
    • 可等待计时器
    • 作业
  • Signal的两种状态
    • 可通知状态
    • 不可通知状态
    • 两种状态的改变可让系统来做,也可手动来做

WaitForSingleObject函数

  • 函数原型

    DWORD WINAPI WaitForSingleObject(
    _In_ HANDLE hHandle,
    _In_ DWORD dwMilliseconds
    );
  • 此函数是用来等待一个内核对象的Signal,如果等待的内核对象是可通知状态,此函数则立马返回,否则,则会阻塞dwMillisecond毫秒的时间,阻塞会导致当前线程变为不可调度
  • 返回值
    • WAIT_TIMEOUT 等待超时
    • WAIT_FAILED 等待失败, 需要调用GetLastError
    • WAIT_OBJECT_0 等待完成, 指定的对象变为有信号了
    • WAIT_ABANDONED 等待Mutex(互斥体)对象, 具体稍候了解

WaitForMultipleObjects函数

  • 函数原型

    DWORD WINAPI WaitForMultipleObjects(  _In_       DWORD  nCount,  _In_ const HANDLE *lpHandles,  _In_       BOOL   bWaitAll,  _In_       DWORD  dwMilliseconds);  
  • 此函数是用来等待多一组内核对象,对参数设置不同,功能不同,总体功能类似WaitForSingleObject

  • 参数
    • nCount等待个数
    • lpHandles等待数组的地址
    • bWaitAll是否全部等待,当此参数为FALSE时,它只会等待最先为可通知状态的内核对象,等到了立即返回
    • dwMilliseconds等待时间
  • 返回值
    • WAIT_OBJECT_0 到 WAIT_OBJECT_0 + nCount - 1也就是说, 返回值是一个范围
    • 最大的返回是 WAIT_OBJECT_0 + nCount - 1
      nCount是要等待的内核对象数量
    • WAIT_ABANDONED_0 到 WAIT_ABANDONED_0 + nCount - 1
      也是等待互斥体的, 稍候了解
    • WAIT_TIMEOUT 等待超时
    • WAIT_FAILED 等待失败, 需要调用GetLastError
原创粉丝点击