讀Windows核心編程 - 5

        Windows2000 提供了一個新的作業內核對象,使你能夠將進程組合在一起,並且創建一個"沙框",以便限制進程能夠進程的操作,最好將作業對象視爲一個進程的容器。與其他所有內核對象相似,創建作業對象需要調用Handle CreateJobObject(PSECURITY_ATTRIBUTES psa, PCTSTR pszName),第一個參數與其他類似Create*函數相同,第二個參數用於給作業對象命名,使它可以供另一個進程通過OpenJobObject訪問。關閉作業對象同樣使用CloseHandle函數,應該知道,關閉作業對象並不會使作業中的所有進程終止運行。該作業對象實際上做了刪除標記,只有當所有進程全部終止後才撤銷。關閉作業對象後,儘管對象沒有立即撤銷,但是該作業無法被進程訪問。通常可以給一個作業加上不同類型的限制:

1. 基本限制和擴展限制,用於防止作業中的進程壟斷系統的資源。

2. 基本的UI限制,用於防止作業中的進程改變用戶界面。

3. 安全性限制,用於防止作業中的進程訪問保密資源(文件,註冊表子關鍵字)

通過下面的代碼,可以給作業加上各種限制:

BOOL SetInformationObject(
     Handle hJob,              //標識要限制的作業
     JOBOBJECTINFORMATION JobObjectInformationClass,   //指明要限制的類型,共四種
     PVOID pJobObjectInformation,             //限制設置值的數據結構的地址
     DWORD cdJobObjectInformationLength           //該結構的大小
);

 限制的類型一共四種,對應的PVOID指向的結構體類型分別如下:

基本限制------------JobObjectBasicLimitInformation------------JOBOBJECT_BASIC_LIMIT_INFORMATION

擴展基本限制------JobObjectExtendedLimitInformation-------JOBOBJECT_EXTENDED_LIMIT_INFORMATION

基本UI限制---------JobObjectBasicUIRestrictions---------------JOBOBJECT_BASIC_UI_RESTRICTIONS

安全性限制---------JobObjectSecurityLimitInformation---------JOBOBJECT_SECURITY_LIMIT_INFORMATION

具體每一種提供了哪些限制這裏不再詳述,可參看核心編程page94。

        對作業實施一些限制後,我們通過CreateProcess創建新的進程,並可以調用AssignProcessToJobObject將該進程指到爲某一作業。這裏調用CreateProcess時要用CREATE_SUSPENDED標誌,因爲如果允許子進程立即執行起來,那麼它將跑出我們的沙框。因此在我們允許它開始運行之前,我們必須調用AssignProcessToJobObject函數將進程放入我們新建的作業中。調用完AssignProcessToJobObject之後,我們調用ResumeThread函數使新進程在作業的限制下開始運行。一旦進程成爲一個作業的一部分,它就不能轉到另一個作業。另外,當屬於作業中的進程創建了另一個進程後,該進程將自動成爲父作業的組成部分。有兩種辦法可以使新產生的進程不屬於該作業:

1. 打開JOBOBJECT_BASIC_LIMIT_INFORMATION的LimitFlags成員中的JOB_OBJECT_BREAKAWAY_OK,告訴系統新產生的進程可以在作業外運行。並且調用CreateProcess時用CREATE_BREAKAWAY_FROM_JOB標誌。

2. 打開JOBOBJECT_BASIC_LIMIT_INFORMATION的LimitFlags成員中的JOB_OBJECT_SILENT_BREAKAWAY_OK標誌。這樣不需要在CreateProcess中傳遞任何其他標誌。

        若要撤銷作業中的進程,可用TerminateJobObject,這類似爲作業中的每個進程調用TerminateProcess。

        QueryInformationJobObject函數可以用來獲取對作業的當前限制,用法與SetInformationObject類似,需要傳遞限制的類型給第二個參數。這個函數也可以用來獲得關於作業的統計信息。方法是爲第二個參數傳遞JobObjectBasicAccountingInformation,並傳遞JOBOBJECT_BASIC_ACCOUNTING_INFORMATION結構的地址。除此之外,還可以獲得I/O統計信息、獲得作業中運行的進程的一組進程ID等。可以使用Performance Data Helper函數庫(PDH.dll)中的函數來檢索作業信息,也可以使用Microsoft Management Console(MMC)來參看作業信息。但是MMC只能爲已經命名的作業對象獲取性能計數器信息,所以我們調用CreateJobObject時應該創建帶有名字的作業對象。

作業通知信息:

         有時候我們需要知道作業中何時生成新進程或者作業中的進程何時終止等消息,比如我們關心的是分配所有CPU的時間是否已經到期,那麼可以非常容易地得到這個通知消息。當作業中的進程尚未用完分配的CPU時間時,作業對象就得不到通知。一旦分配的所有CPU時間已經用完,windows就強制撤銷作業中的所有進程,並將情況通知作業對象。通過調用WaitForSingleObject就可以容易地跟蹤這個事件。但是如果想獲得更高級的通知信息,如果進程創建/終止等。如果想要得到這些通知消息,必須將更多的基礎結構放入應用程序。特別是,必須創建一個I/O完成端口內核對象,並將作業對象或多個作業對象與完成端口關聯起來。然後,必須讓一個或多個線程在完成端口上等待作業通知的到來,這樣它們才能得到處理。

        一旦創建了I/O完成端口,通過調用SetInformationJobOject函數,就可以將作業與該端口關聯起來,如下:

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

         當上面的代碼運行時,系統將監視該作業的運行,當事件發生時,它將事件送往I/O完成端口。線程通過GetQueuedCompletionStatus函數來監控I/O端口。可以監控很多事件的發生,比如:當作業中沒有進程運行時、當一個進程添加到作業中、當一個進程終止運行等等情況。具體用法參看核心編程page105。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章