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

Windows提供了一个作业(Job)内核对象,它允许将进程组合在一起并创建一个"沙箱"来限制进程能够做什么。最好将作业对象想象成一个进程容器。但是,创建只包含一个进程的作业也是非常有用,因为这样可以对进程施加平时不能施加的限制。

通过给函数BOOL IsProcessInJob (HANDLE ProcessHandle,HANDLE JobHandle,PBOOL Result);
的第二个参数传递NULL,可以验证某个进程是否在一个现有的作业控制之下运行。如果进程已与一个作业关联,那么就无法将该进程或它的任何子进程从作业中去除。这个安全特性可以确保进程无法摆脱对它施加的限制。

默认情况下,在Windows vista中通过Windows资源管理器来启动一个应用程序,进程会自动同一个专用的作业关联,此作业的名称使用"PCA"字符串前缀。Windows Vista提供这个功能的目的是检测兼容性问题。所以,如果你已经像第4章描述的那样为应用程序定义了一个manifest,windows资源管理器就不会将你的进程同"PCA"前缀的作业关联,它会假定你已经解决了任何可能的兼容性问题。但是在需要调试应用程序的时候,如果调试器是从Windows资源管理器启动的,即使有一个mainifest,应用程序也会从调试器继承带有"PCA"前缀的作业,一个简单的解决方案是从命令行而不是Windows 资源管理器中启动调试器,这样就不会与作业关联。

如果确定在自己的代码中不再访问作业对象,就必须调用CloseHandle来关闭它的句柄。关闭一个作业对象,不会迫使作业中的所有进程都终止运行,作业对象实际只是加了一个删除标记,只有在作业中的所有进程都已终止运行之后,才会自动销毁。关闭作业的句柄会导致所有的进程都不可访问此作业,即使它仍然存在。

可以向作业应用以下几种类型的限制:
1) 基本限额和扩展基本限额,用以防止作业中的进程独占系统资源;
2) 基本的UI限制,用以防止作业中的进程修改用户界面;
3) 安全限额,用以防止作业内的进程访问安全资源(文件、注册表子项等)。

通过调用函数SetInformationJobObject向作业施加限制。作业中的进程可以调用QueryInformationJobObject获得所属作业的相关信息(为作业句柄参数传递NULL值),这使得进程可以看到自己被施加了哪些限制。不过,如果为作业句柄参数传递NULL值,SetInformationJobObject函数调用会失败--目的是防止进程删除施加于自己身上的限制。

在创建子进程之后且在允许它运行之前,可以调用函数AssignProcessToJobOjbect来将进程显式地放入新建的作业中。该函数只允许将尚未分配给任何作业的一个进程分配给一个作业。可以使用IsProcessInJob函数来对此进程查询。一旦进程属于某个作业,它就不能再移动到另一个作业中,也不能称为“无业的”。

当作业中的一个进程生成了另一个进程的时候,新进程将自动称为父进程所属的作业的一部分。但可以通过一些方式改变这种行为。

要“杀死”作业内部的所有进程,可以调用函数:
BOOL TerminateJobOjbect(HANDLE hJob, UINT uExitCode);

通过调用GetProcessTimes函数,可以获得任何一个进程的CPU占用时间信息,即使此进程不属于任何一个作业。

作业中的进程如果尚未用完已分配的CPU时间,作业对象就处于未触发状态的。一旦作业用完所有已分配的CPU时间,Windows就会强行“杀死”作业中的所有进程并触发作业对象。

你可能感兴趣的:(编程,windows,UI,null,扩展,作业)