《Windows 核心编程》第五版 第5章:作业

4 篇文章 0 订阅

第5章 作业

  • 作业能够将进程组合在一起,并且创建一个“沙框”,以便限制进程能够进行的操作
  • 可以把作业对象视为一个进程容器
  • 创建单个进程的作业,可以对该进程添加平时不能加的限制

一些基本知识

  • 关闭作业对象不会迫使作业中的所有进程终止运行,作业对象做了删除标记,只有当作业中的所有进程全部终止运行之后,该作业对象才被自动撤消。
  • 关闭作业的句柄后,尽管作业仍在,但是作业无法被所有进程访问。

5.1 对作业进程的限制

限制类型

  • 基本限制和扩展基本限制,用于 防止 作业中的 进程垄断系统的资源
  • 基本的 UI 限制,用于 防止 作业中的 进程改变用户界面
  • 安全性限制,用于 防止 作业中的 进程访问保密资源(文件、注册表子关键字等)

添加限制

  • 可以通过调用函数指明用于作业的限制条件
限制条件
  • CPU的亲缘关系、工作区大小、每个进程占用的 CPU 时间等等

书中列出一些类型:

  1. JOB_OBJECT_LIMIT_JOB_TIME 标志:限制当前活动进程使用了多少 CPU 时间

  2. JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME 标志:与上面的标志互斥,不减去已终止运行的进程的 CPU 时间

  3. SchedulingClass 成员 :改变拥有相同优先级的作业的相对调度关系,范围:0~9,默认为5,值越大、系统给该作业的运行时间量越长,值越小、系统给该作业的运行时间量越短。尽可能避免使用大数字,大的时间量会降低系统中其他作业、进程和线程的总体响应能力。

    (Microsoft 计划在将来的 Windows 版本中对线程调度程序进行更重要的修改,因为它认
    为操作系统应该为作业、进程和线程提供更宽松的线程调度环境。)

  4. JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 限制标志:可使系统为与作业相关的每个进程关闭“未处理的异常情况”对话框。

    系统通过调用 SetErrorMode 函数,将作业中的每个进程的 SEM_NOGPFAULTERRORBOX 标志传递给它。作业中产生未处理的异常情况的进程会立即终止运行,不显示任何用户界面。对于服务程序和其他面向批处理的作业来说,这是个非常有用的限制标志。如果没有这个标志,作业中的进程就会产生一个异常情况,并且永远不会终止运行,从而浪费了系统资源

  5. JOBOBJECT_EXTENDED_LIMIT_INFORMATION 结构:对作业设置扩展限制

    在这里插入图片描述

  6. JOB_OBJECT_UITIMIT_HANDLES 标志:作业中没有一个进程能访问该作业外部的进程创建的 USER 对象

    如果试图在作业内部运行Microsoft Spy++,那么除了Spy++ 自己创建的窗口外,你看不到任何别的窗口。
    图 5-1 显示的 Spy++ 中打开了两个 MDI 子窗口。注意,Threads 1的窗口包含一个系统中的线程列表。这些线程中只有一个线程,即 000006AC SPYXX 似乎创建了一些窗口。这是因为我是在它自己的作业中运行 Spy++ 的,并且限制了它对 UI 句柄的使用。
    在这里插入图片描述
    在同一个窗口中,可以看到 MSDEVEXPLORER 两个线程,可以保证,这些线程肯定创建了窗口,但是 Spy++ 无法访问它们。
    在对话框的右边,可以看到 Windows 3窗口,在这个窗口中,Spy++ 显示了桌面上存在的所有窗口的层次结构。注意,它只有一个项目,即 00000000。Spy++ 必须将它作为占位符放在这里。

    UI限制是单向的。作业外部的进程能看到作业内部的进程创建 USDR 对象。

    如果我在一个作业中运行 Notepad,并在作业的外部运行 Spy++ ,若在 Notepad 上设置了 JOB_OBJECT_UILIMIT_HANDLES 标志。 在Spy++的作业中,能看到 NotePad 窗口,但是 Notepad 因为设置了限制,所以看不到 Spy++ 窗口。

    作业组成部分的进程,要与作业外部的进程通信,可以限制 UI 句柄

  7. UserHandGrantAccess 函数:解决 UI 句柄限制的问题,作业中的进程将窗口消息,发送或显示在作业外部的进程创建的窗口中

    在这里插入图片描述

  8. JOBOBJECT_SECURITY_LIMIT_INFORMATION:安全性相关的限制类型,一旦使用,就无法取消安全性限制

    在这里插入图片描述
    在这里插入图片描述

5.2 将进程放入作业

  • 子进程不属于作业的组成部分
  • 当创建子进程后,子进程开始运行前,必须现实地将进程放入新创建的作业

可以调用下面的代码:
在这里插入图片描述
在这里插入图片描述

5.3 终止作业中所有进程的运行

常用的操作是撤销作业中的所有进程,只需要调用下面的代码:
在这里插入图片描述

5.4 查询作业统级信息

  • 可以使用 QueryInformationJobObject 函数来获取 对作业当前的限制信息,也可以用它来获取作业的统计信息

  • 可以调用 QueryInformationJobObject 为第二个参数传递 JobObjectBasicAccountingInformation 并传递 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION 结构的地址,来获取基本的统计信息 :

    在这里插入图片描述
    在这里插入图片描述

  • 此外,还可以进行 一次函数调用同时查询 基本统计信息和 I/O 统级信息,必须为第二个参数传递 JobObjectBasicAndIoAccountingInformation 并传递 JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION 结构的地址:

    在这里插入图片描述
    该结构告诉你 作业中的进程 已经执行的读、写和非读 / 写操作的数量(以及在这些操作期间传送的字节数)

  • 此外,可以用下面这个 GetProcessIoCounter 函数,以便获取 不是这些作业中的进程的这些信息

    在这里插入图片描述

  • 获取当前作业中的 一组进程ID,可以执行以下代码

    在这里插入图片描述

  • 操作系统实际上保存了更多的关于作业的信息,使用性能计数器 来进行操作。可以使用 Performance Data Helper 函数库
    (P D H . d l l)中的函数来检索这些信息。也可以使用 Microsoft Management Console(MMC)的Performance Monitor Snap-In来查看作业信息。

    如图所示,显示了系统中的作业对象可以使用一些计数器
    在这里插入图片描述
    注意,当调用 CreateJobObject 函数时,只能为已经赋予名字的作业获取性能计数器信息。由于这个原因,即使不打算按名字来 共享跨越进程 的作业对象,也应该创建带有名字的这些对象。

5.5 作业通知信息

通知信息包括

  • 作业中的所有进程何时终止运行
  • 分配的全部 CPU 时间是否已经到期
  • 作业中何时生成新进程或作业中的进程何时终止运行

如果关心这些时间,还需要做一些工作

得到通知信息

分配的所有 CPU 时间是否已经到期
  • 一旦分配的所有 CPU 时间已经用完, Windows 就强制撤消作业中的所有进程,并将情况通知作业对象。
  • 通过调用 WaitForSingleObject(或类似的函数)可以很容易跟踪这个事件
  • 可以在晚些时候调用 SetInformationJobObject 函数,使作业对象恢复未通知状态,并为作业赋予更多的 CPU 时间。
整个作业何时运行结束
  • 由于许多作业启动时有一个父进程始终处于工作状态,直到它的所有子进程运行结束,因此只需要在父进程的句柄上等待,就可以知道
  • StartRestrictedProcess 函数用于显示分配给作业的 CPU 时间何时到期,或者作业中的进程何时终止运行
获得更高级的通知信息:进程创建/终止运行等
  • 必须将更多的基础结构放入应用程序,特别是,必须创建一个 I/O 完成端口内核对象,并将作业对象或多个作业对象与完成端口关联起来
  • 然后,必须让一个或多个线程在完成端口上等待作业通知的到来,这样它们才能得到处理
  • 一旦创建了 I/O 完成端口,通过调用 SetInformationJobObject 函数,就可以将作业与该端口关联起来,如下面的代码所示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.6 JobLab 实例应用程序

  • JobLab 应用程序 “05JobLab.exe” 使你很容易对作业进行实验性操作
  • 该应用程序创建了一个 I/O 完成端口,并将作业对象与它相关联。这样就可以对来自作业的通知进行监控,并可
    显示在窗口底部的列表框中。
  • 应用程序中除了使用基本限制和扩展限制条件外,还可以打开和关闭各种 UI 限制

在这里插入图片描述

  • 源代码定义了一个 Cjob C++ 类,用于封装操作系统的作业对象,操作起来更容易,不必到处传递作业句柄,还减少了平常调用 QueryInformationJobObjectSetInformationJobObject 函数时需要进行的转换工作量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值