很久之前看到這一小節的時候,基本是一頭霧水、半知半解的感覺,因為有太多不熟悉的概念。當時也在網上找了一些資料和部落格來看,感覺協助也不大,於是就跳過了。今天論壇的左懶童鞋突然問了我這個地方應該如何理解,於是決定再好好去看看書,驗證自己的想法。
書上主要原話:
在正在運行終端服務的電腦中,有多個用於核心對象的命名空間。其中一個是全域命名空間,所有用戶端都能訪問的核心對象要放在這個命名空間。對於兩個或多個會話正在運行同一個應用程式的情況,這樣的安排可以避免會話之間彼此幹擾---一個會話不會訪問另一個會話的對象,即使對象的名稱相同(關鍵點)。(會話這個概念比較抽象,還沒有找到一個適合的描述,我個人的感覺會話就是類似於一個域,然后里面有一堆進程。)
對於服務開發人員,由於必須在與用戶端應用程式不同的一個會話中運行,所以會影響到共用核心對象的命名規範。任何對象想要和使用者應用程式共用,都必須在全域命名空間中建立它。快速切換使用者也會帶來類似的問題。我們知道,利用快速切換使用者功能,不同的使用者可以登入不同的會話,並分別啟動自己的使用者應用程式。如果我們寫的一個服務要與這些應用程式通訊,就不能假定它和使用者應用程式在同一個會話中運行。
針對上面那兩段話,我在Win7環境寫了幾行代碼,做了個簡單的測試。
首先在admin帳戶(一個會話)中,我在程式中用:
HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("Global\\Handle")) ;
建立一個放在全域命名空間中的互斥量對象,並調用Sleep(INFINITE)掛起程式,讓個核心對象一直保持著。
然後將我的應用程式複製到guest帳戶的檔案夾中,切換guest帳戶(另一個會話)並運行這個程式,發現互斥量建立失敗,CreateMutex返回NULL,ErrorCode為ERROR_ALREADY_EXISTS。
然後,我將上述代碼改為:
HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("Local\\Handle")) ;
隨後執行同上的操作,發現在guest帳戶中,這個程式也能夠成功建立這個同名的核心對象。
於是,也就是驗證了我的想法,其實就是一個命名空間的問題,好吧,我也不知道自己想表達些什麼,感覺在說廢話.......
測試代碼:
#include<windows.h>#include<cstdio>#include<iostream>int main(void){//在全域命名空間中建立核心對象,用不同帳戶運行該程式,不能建立同名的核心對象。//HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("Global\\Handle")) ; //在局部命名空間中建立核心對象,用不同帳戶運行該程式,可以建立同名的核心對象。//HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("Local\\Handle")) ;HANDLE hMutex = CreateMutex(NULL,FALSE,TEXT("Handle")) ; //同上//在局部命名空間測試樣本中要用GetLastError檢測,在全域命名空間測試樣本中要判斷hMutex是否為NULLif(NULL == hMutex || GetLastError() == ERROR_ALREADY_EXISTS) {printf("已經存在互斥量對象\n") ;return 0 ;}printf("成功建立互斥量對象\n") ;Sleep(INFINITE) ;return 0 ;}