Windows 提供了 Job 让用户将一些进程视为一个,并且可以对Job作出限制。

必须在进程创建后,在把进程移动到JOB中。所以必须先SUSPEND进程,这个时候进程不能执行任何代码,之后再将进程移动到JOB中,然后恢复进程。能不能用JOB限制AV?Check

通过BOOL IsProcessInJob( HANDLE hProcess, HANDLE hJob, PBOOL pbInJob);判断当前进程是否在JOB中,第二个参数传NULL。

如果进程已经在JOB中,无法将进程移出JOB,子进程也会自动在JOB中

默认情况下通过Exploerer创建的进程关联 PCA 前缀的JOB。所以想要再关联JOB就会失败。 如果定义了manifest 文件就不会自动关联JOB 但是如果你想要调试你的程序,如果调试器被Explorer 启动。你的进程即使带有manifest,也会继承 PCA 前缀的JOB。一个解决方法就是使用命令行启动调试器

创建JOB

HANDLE CreateJobObject( PSECURITY_ATTRIBUTES psa, PCTSTR pszName);

通过名称打开JOB

HANDLE OpenJobObject(DWORD dwDesiredAccess , BOOL bInheritHandle, PCTSTR pszName);

关闭JOB,不会停止JOB关联的进程。只是将JOB标记为删除,当关联进程结束后,JOB自动删除。

当关闭Close Job Handle 后,JOB Handle 就不能被使用了。

在JOB进程上限制

有下面几种限制

  • 基本的对于系统资源的限制

  • 限制UI,不然限制在用户界面上

  • 安全限制,阻止进程接触资源 files 、 registry subkeys

BOOL SetInformationJobObject(
    HANDLE hJob,
    JOBOBJECTINFOCLASS JobObjectInformationClass, 
    PVOID pJobObjectInformation, 
    DWORD cbJobObjectInformationSize);

第一个参数是JOB Handle 第二个参数是 一个 枚举类型关于 想要限制的类型 第三个参数指向 限制设置结构体的指针 第四个参数指向 结构体大小

下图展示限制类型

将进程放入JOB

BOOL AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess);

但是如果进程已经在JOB中,就不然重新放到JOB中。子进程默认放入父进程的JOB中,可以用下面两个方法来改变

  • 开启 JOBOBJECT_BASIC_LIMIT_INFORMATION’s LimitFlags 中的 JOB_OBJECT_LIMIT_BREAKAWAY_OK,然后CreateProcess 使用 CREATE_BREAKAWAY_FROM_JOB Flag

  • 开启 JOBOBJECT_BASIC_LIMIT_INFORMATION’s LimitFlag 中的 JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK FLag , 这个使用 CreateProcess 不需要显式声明

结束JOB中所有进程

Kill Job中的进程

BOOL TerminateJobObject( HANDLE hJob, UINT uExitCode);

这与对所有进程调用TerminateProcess 类似

Querying Job Statistics

作业通知

当JOB耗尽了分配的CPU时间,就会强制结束JOB中所有的进程,并signal(触发作业对象)。 可以使用WaitForSingleObject 捕获这个事件,并可以在之后通过SetInformationJobObject 修改JOB 为 nonsignaled 状态,并分配更多CPU时间。

可以使用 I/O completion port 来检测JOB中的情况