Job可以被理解为进程的容器,而它又不是单纯的容器,按照书本上所讲的,Job是一个沙盒,它可以为在它里面运行的进程增加一系列的限制。包括每一个进程或者整个Job能够使用的User mode CPU时间,每一个进程或者整个Job最多能使用的内存,Job内的进程能否访问到Job外的用户对象(例如窗口,画刷),能否退出Windows,能否访问剪切板等等。当限制设定之后,我们就可以创建一个进程,并将它放置到Job之中。
1、Job对象即使引用数到了0也不会立刻释放,它会等到Job内所有的进程都结束了再释放,但是,在这种情况下,Job的名称将会失效,不能再通过Job的名称和Job的句柄来向Job中增加新的进程。
2、Job可以设置当前可运行进程最大数量。当超过这个最大数量时,任何新进程都将被立刻终止(Terminate)。
3、Job可以在同一进程优先级下设定调度的微调值(SchedulingClass)。微调值高的Job中的线程比微调值低的获得更多的CPU时间。
4、Job可以限制对用户对象以及Windows界面的访问,例如不许退出窗口,不能访问剪切板等。这意味着Job内的进程无法获取到Job外进程的对象,比如HWND,但是Job外的进程可以获得Job内进程的对象。
5、对Job设定了OBOBJECT_SECURITY_LIMIT_INFORMATION后,该设定不能被取消。
7、当一个进程被加入到Job中后,没有特殊的说明,那么该进程的所有子进程都将被纳入到Job里。当然,通过JOB_OBJECT_LIMIT_BREAKAWAY_OK或者JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK。Job内进程的子进程就可以不被自动纳入到Job中,两者区别在于,后者将所有子进程自动的赶出Job,而前者的子进程需要在CreateProcess时指定CREATE_BREAKAWAY_FROM_JOB。
8、如果Job被强制关闭,那么Job内的所有进程都将被终止(Terminate)
9、当Job所指定的CPU时间耗光后,Job HANDLE将处于Signaled状态,Wait系列函数就可以响应这个事件。
---------------------------------------------------
Job相关API介绍
1、CreateJobObject, 创建一个具名的Job对象
HANDLE WINAPI CreateJobObject(
__in_opt LPSECURITY_ATTRIBUTES lpJobAttributes,
__in_opt LPCTSTR lpName
);
该API创建一个Job内核对象,可以为对象的名字前加上"Global\" or "Local\" 来指定名字是全局的还是局部的,该对象名字和其他类型的具名对象同在一个命名空间,如果名字冲突,会导致函数失败。
Job的所有工作机制都是围绕这个内核对象展开的,在内核中所有对Job包含的进程的限制,都是通过获取进程的内核对象中挂接的Job对象,根据Job对象的属性来限制进程所能够完成的操作,Job内核对象在WRK中是这样定义的:
typedef struct _EJOB {
KEVENT Event;
//
// All jobs are chained together via this list.
// Protected by the global lock PspJobListLock
//
LIST_ENTRY JobLinks;//创建一个Job对象的时候,会将其挂入系统Job对象链表中,
//
// All processes within this job. Processes are removed from this
// list at last dereference. Safe object referencing needs to be done.
// Protected by the joblock.
//
LIST_ENTRY ProcessListHead; //进程链表头,AssignProcessToJobObject时,或者Job中的进程创建子进程,把进程内核对象挂入该表
ERESOURCE JobLock;
//
// Accounting Info
//
LARGE_INTEGER TotalUserTime;
LARGE_INTEGER TotalKernelTime;
LARGE_INTEGER ThisPeriodTotalUserTime;
LARGE_INTEGER ThisPeriodTotalKernelTime; //统计已使用的用户和内核时间
ULONG TotalPageFaultCount; //统计页错误次数
ULONG TotalProcesses; //统计曾属于Job的进程数
ULONG ActiveProcesses; //目前活动的进程数
ULONG TotalTerminatedProcesses;//超出时间,终止了的进程数
//
// Limitable Attributes
//
LARGE_INTEGER PerProcessUserTimeLimit; 进程时间限制
LARGE_INTEGER PerJobUserTimeLimit; Job时间限制
ULONG LimitFlags; 限制标志哪个起作用
SIZE_T MinimumWorkingSetSize;
SIZE_T MaximumWorkingSetSize; //工作集
ULONG ActiveProcessLimit; //最大活动进程限制
KAFFINITY Affinity; //CPU集限制
UCHAR PriorityClass; //优先级
//对应JOBOBJECT_BASIC_LIMIT_INFORMATION
//
// UI restrictions
//
ULONG UIRestrictionsClass; 对应JOBOBJECT_BASIC_UI_RESTRICTIONS
//
// Security Limitations: write once, read always
//
ULONG SecurityLimitFlags;
PACCESS_TOKEN Token;
PPS_JOB_TOKEN_FILTER Filter; 对应JOBOBJECT_SECURITY_LIMIT_INFORMATION
//
// End Of Job Time Limit
//
ULONG EndOfJobTimeAction; 对应JOBOBJECT_END_OF_JOB_TIME_INFORMATION
PVOID CompletionPort;
PVOID CompletionKey; //对应JOBOBJECT_ASSOCIATE_COMPLETION_PORT
ULONG SessionId;
ULONG SchedulingClass;
ULONGLONG ReadOperationCount;
ULONGLONG WriteOperationCount;
ULONGLONG OtherOperationCount;
ULONGLONG ReadTransferCount;
ULONGLONG WriteTransferCount;
ULONGLONG OtherTransferCount;
//
// Extended Limits
//
IO_COUNTERS IoInfo; // not used yet
SIZE_T ProcessMemoryLimit;
SIZE_T JobMemoryLimit;
SIZE_T PeakProcessMemoryUsed;
SIZE_T PeakJobMemoryUsed;
SIZE_T CurrentJobMemoryUsed; 对应JOBOBJECT_EXTENDED_LIMIT_INFORMATION
KGUARDED_MUTEX MemoryLimitsLock;
//
// List of jobs in a job set. Processes within a job in a job set
// can create processes in the same or higher members of the jobset.
// Protected by the global lock PspJobListLock
//
LIST_ENTRY JobSetLinks;
//
// Member level for this job in the jobset.
//
ULONG MemberLevel;
//
// This job has had its last handle closed.
//
#define PS_JOB_FLAGS_CLOSE_DONE 0x1UL
ULONG JobFlags;
} EJOB;
typedef EJOB *PEJOB;
BOOL WINAPI AssignProcessToJobObject(
__in HANDLE hJob,
__in HANDLE hProcess
);
BOOL WINAPI SetInformationJobObject(
__in HANDLE hJob,
__in JOBOBJECTINFOCLASS JobObjectInfoClass, //枚举型型标识使用哪类限制
__in LPVOID lpJobObjectInfo, //根据JobObjectInfoClass ,使用对应的结构
__in DWORD cbJobObjectInfoLength //lpJobObjectInfo的大小
);
JOBOBJECTINFOCLASS 枚举值及所对应的lpJobObjectInfo指向的结构体
JOBOBJECT_BASIC_LIMIT_INFORMATION 基本的限制(包括每个进程的时间,Job时间,工作集,CPU集,调度优先级)具体参见MSDN
JOBOBJECT_EXTENDED_LIMIT_INFORMATION 在BASIC的基础上加了对内存的限制 参见MSDN
JOBOBJECT_BASIC_UI_RESTRICTIONS 对UI资源的限制,包括(创建桌面,设置显示,关机,原子表,获取窗口句柄,获取剪切板,设置系统参数)参见MSDN
MSDN中关于该函数有这样的描述
You must set security limitations individually for each process associated with a job object, rather than setting them for the job object itself. For information, see Process Security and Access Rights. 必须为每个进程单独的设置安全限制
4、 QueryInformationJobObject
BOOL WINAPI QueryInformationJobObject(
__in_opt HANDLE hJob,
__in JOBOBJECTINFOCLASS JobObjectInfoClass,
__out LPVOID lpJobObjectInfo,
__in DWORD cbJobObjectInfoLength,
__out_opt LPDWORD lpReturnLength
);
如果为函数第二个参数传递JobObjectBasicAccountingInformation 对应的lpJobObjectInfo 应该为JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
如果传递JobObjectBasicAndIoAccountingInformation 对应的lpJobObjectInfo 应该为JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION
如果传递JobObjectBasicProcessIdList 对应的lpJobObjectInfo 应该为 JOBOBJECT_BASIC_PROCESS_ID_LIST
具体参见MSDN