作業 -> 【Windows核心編程(第五版)】

作業

Windows提供了一個作業內核對象, 允許我們將進程組合在一起並創建一個“沙箱”來限制進程能做什麼.

// 驗證進程是否在一個作業控制下運行
BOOL IsProcessInJob(HANDLE hProcess, HANDLE hJob, PBOOL pbInJob);
  • 默認下,用資源管理器啓動一個應用,進程自動與一個專用作業關聯
  • 如爲應用程序定義了一個清單,Windows資源管理器不會將我們的進程同專用作業關聯。調試應用時,應用會從調試器繼承專用作業。
  • 如果用命令行啓動調試,調試器不會與專用作業關聯,調試的應用也不會。
// 創建作業內核對象
HANDLE CreateJobObject(
DWORD dwDesiredAccess, 
BOOL bInheritHandle, 
PCTSTR pszName);

// 打開現有作業對象
HANDLE OpenJobObject(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
PCTSTR pszName
);

// 關閉作業對象,表示不再訪問此對象。
// 作業對象在作業中所有進程都已終止運行後,才自動銷燬
CloseHandle(HANDLE hWndJob);

// 把進程分配給作業
BOOL AssignProcessToJobObject(HANDLE hJob, HANDLE hProcess);

對作業中進程施加限制

  1. 基本限額和擴展基本限額
  2. 基本的UI限制
  3. 安全限額
BOOL SetInformationJobObject(
HANDLE hJob, 
JOBOBJECTINFOCLASS JobObjectInformationClass, 
PVOID pJobObjectInformation, 
DWORD cbJobObjectInformationSize);

typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION
{
// 用戶模式時間限制--針對進程
LARGE_INTEGER PerProcessUserTimeLimit;
// 用戶模式時間限制--針對作業
LARGE_INTEGER PreJobUserTimeLimit;
// 標識有效字段
DWORD LimitFlags;
DWORD MinimumWorkingSetSize;
DWORD MaximumWorkingSetSize;
DWORD ActiveProcessLimit;
DWORD_PTR Affinity;
// 作業的優先級類
DWORD PriorityClass;
// 同一優先級類的作業的相對優先級
DWORD SchedulingClass;
};

typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
IO_COUNTERS IoInfo;
SIZE_T ProcessMemoryLimit;
SIZE_T JobMemoryLimit;
SIZE_T PeakProcessMemoryUsed;
SIZE_T PeakJobMemoryUsed;
};

typedef struct _JOBOBJECT_BASIC_UI_RESTRICTIONS
{
// JOB_OBJECT_UI_LIMIT_HANDLES 不可使用作業外進程的用戶對象句柄
// ...
DWORD UIRestrictionsClass;
};

BOOL UserHandleGrantAccess(
// 用戶對象
HANDLE hUserObj,
HANDLE hJob,
BOOL bGrant
);

typedef struct _JOBOBJECT_SECURITY_LIMIT_INFORMATION
{
DWORD SecurityLimitFlags;
// 作業令牌
HANDLE JobToken;
PTOKEN_GROUPS SidsToDisable;
PTOKEN_PRIVILEGES PrivilegesToDelete;
PTOKEN_GROUPS RestrictedSids;
};

將進程放入作業

// 一旦進程已屬作業的一部分,就不能再移動到另一個作業或從作業中移除
BOOL AssignProcessToJobObject(
HANDLE hJob,
HANDLE hProcess
);

// 作業中進程生成的進程默認也在作業中
// 作業基礎限額有標誌,JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK新進程不屬於作業
// 有標誌,JOB_OBJECT_LIMIT_BREAKAWAY_OK,CreateProcess時要指定CREATE_BREAKAWAY_FROM_JOB纔可

殺死作業內所有進程

BOOL TerminateJobObject(
HANDLE hJob,
UINT uExitCode
);

查詢作業信息

// 4類限額信息
// 統計信息
// 作業內進程列表
// JobObjectBasicAccountingInformation
// JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
BOOL QueryInformationJobObject(
HANDLE hJob,
JOBOBJECTINFOCLASS JobObjectInformationClass,
PVOID pvJobObjectInformation,
DWORD cbJobObjectInformationSize,
PDWORD pdwReturnSize
);

typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
{
LARGE_INTEGER TotalUserTime;
LARGE_INTEGER TotalKernelTime;
LARGE_INTEGER ThisPeriodTotalUserTime;
LARGE_INTEGER ThisPeriodTotalKernelTime;
DWORD TotalPageFaultCount;
DWORD TotalProcess;
DWORD TotalTerminatedProcesses;
};

typedef struct JOBOBJECT_BASIC_AND_IO_COUNTING_INFORMATION
{
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicInfo;
IO_COUNTERS IoInfo;
};

typedef struct _IO_COUNTERS
{
ULONGLONG ReadOperationCount;
ULONGLONG WriteOperationCount;
ULONGLONG OtherOperationCount;
ULONGLONG ReadTransferCount;
ULONGLONG WriteTransferCount;
ULONGLONG OtherTransferCount;
};

// 對不屬於作業的進程
BOOL GetProcessIoCounters(
HANDLE hProcess,
PIO_COUNTERS pIoCounters
);

// JobObjectBasicProcessIdList
// JOBOBJECT_BASIC_PROCESS_ID_LIST

typedef struct _JOBOBJECT_BASIC_PROCESS_ID_LIST(
// 傳入(要保證足夠大)
DWORD NumberOfAssignedProcesses;
// 傳出
DWORD NumberOfProcessIdsInList;
// 數組首地址
DWORD ProcessIdList[1];
);

作業通知

作業用完所有已分配的CPU時間,就會強行“殺死”作業中的所有進程並觸發作業對象。
之後,還可用SetInformationJobObject把作業對象重置爲未觸發狀態。
1. 創建一個I/O完成端口。
2. 將我們的作業對象與完成端口關聯。
3. 須有一個或多個線程等待作業通知到達完成端口。

JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp;
joacp.CompletionKey = 1;
joacp.CompletionPort = hIOCP;
SetInformationJobObject(
hJob, 
JobObjectAssociateCompletionPortInformation,
&joacp,
sizeof(joacp));

// 線程監視完成端口
BOOL GetQueuedCompletionStatus(
HANDLE hIOCP,
PDWORD pNumBytesTransferred,
// 區分作業
PULONG_PTR pCompletionKey,
POVERLAPPED *pOverlapped,
DWORD dwMilliseconds
);

默認下,分配給作業的CPU時間到期,它的所有進程都自動終止,且不投遞 JOB_OBJECT_MSG_END_OF_JOB_TIME

JOBOBJECT_END_OF_JOB_TIME_INFORMATION joeojti;
// JOB_OBJECT_TERMINATE_AT_END_OF_JOB 默認值
// JOB_OBJECT_POST_AT_END_OF_JOB
joeojti.EndOfJobTimeAction = xx;
SetInformationJobObject(hJob, JobObjectEndOfJobTimeInformation,
&joeojti,
sizeof(joeojti));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章