關於Mutex的使用問題

權限問題

 

互斥量對象會一直存活着直到使用它的最後一個程序關閉其句柄,因此它能在初始創建它的應用程序退出後保留相當長的時間。因爲此對象被廣泛地共享,所以它必須被賦予明確的許可以允許任何人使用它。事實上,“缺省”許可幾乎從不適用。 對於 SYNCHRONIZE和MUTEX_ALL_ACCESS 權限,因爲非管理員沒有這些權限(僅有上列的少許)互斥量不能被打開或者獲取,於是CreateMutex() 和OpenMutex() 返回NULL。因此,當對象已經存活於內存中時硬性改變其上的許可配置:(需要調用 SetKernelObjectSecurity(),下列程序片斷展示一個程序如何才能打開互斥量並安裝一個新的 DACL,此 DACL 即使在程序退出後也仍然保持着,只要任一其他程序還維護有它的句柄)

...
                        // open the mutex that we're going to adjust
                        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "DBWinMutex");
                        // create SECURITY_DESCRIPTOR with an explicit, empty DACL
                        // that allows full access to everybody
                        SECURITY_DESCRIPTOR     sd;
                        InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
                        SetSecurityDescriptorDacl(
                        &sd,            // addr of SD
                        TRUE,           // TRUE=DACL present
                        NULL,           // ... but it's empty (wide open)
                        FALSE);         // DACL explicitly set, not defaulted
                        // plug in the new DACL
                        SetKernelObjectSecurity(hMutex, DACL_SECURITY_INFORMATION, &sd);
                        ...

 

例子:

 

HANDLE hEventQuit = NULL;
hEventQuit = CreateEvent(NULL, FALSE, FALSE, NULL);

DWORD WINAPI ThreadOperation()
{
    HANDLE hMutex = NULL;

    // Create SECURITY_DESCRIPTOR with an explicit, empty DACL
    // that allows full access to everybody
    SECURITY_DESCRIPTOR sd;
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(
        &sd,            // addr of SD
        TRUE,           // TRUE=DACL present
        NULL,           // ... but it's empty (wide open)
        FALSE);         // DACL explicitly set, not defaulted

    // Open the mutex that we're going to adjust
    hMutex = OpenMutex(MUTEX_ALL_ACCESS, NULL, _T("Global\\MutexName"));
    if (NULL == hMutex)
    {
        SECURITY_ATTRIBUTES sa;
        sa.nLength = sizeof(sa);
        sa.bInheritHandle = FALSE;
        sa.lpSecurityDescriptor = &sd;
        hMutex = CreateMutex(&sa, FALSE, _T("Global\\MutexName"));
    }
    // Plug in the new DACL
    SetKernelObjectSecurity(hMutex, DACL_SECURITY_INFORMATION, &sd);

    if (NULL != hMutex)
    {
        HANDLE hMutexHandles[] = {hMutex, hEventQuit};
        DWORD dwMutexResult = WaitForMultipleObjects(
            _countof(hMutexHandles), 
            hMutexHandles, 
            FALSE, 
            INFINITE);
        switch(dwMutexResult)
        {
        case WAIT_OBJECT_0:     //scucess
            //Do yourself things            
            break;
        case WAIT_OBJECT_0 + 1: //quit,cancel thread
            break;
        case WAIT_ABANDONED:
            //not release mutex and not response
            break;
        default:    //failure
            //decide operation yourself
            break;
        }
        ReleaseMutex(hMutex);
    }
    else
    {
        CloseHandle(hMutex); 
    }

    return 0;
}

 

 

延伸:

 

互斥對象

 

1. 互斥對象(mutex)屬於內核對象,它能夠確保線程擁有對單個資源的互斥訪問權。

 

2. 互斥對象包含一個使用數量,一個線程ID和一個計數器。

 

3. ID用於標識系統中的哪個線程當前擁有互斥對象,計數器用於指明該線程擁有互斥對象的次數。

 

涉及到三個函數:

 

1. CreateMutex:創建互斥對象,返回互斥對象的句柄,其中第二個參數如果是TRUE,表示調用該函數的線程擁有互斥對象的所有權,即互斥對象處於非空閒狀態。如果是FALSE,則表示當前互斥對象處於空閒狀態,其他線程可以佔用。

 

2. WaitForSingleObject(WaitForMultipleObject):等待互斥對象的使用權,如果第二個參數設置爲INFINITE,則表示會持續等待下去,直到擁有所有權,纔有權執行該函數下面的語句。一旦擁有了所有權,則會將互斥對象的的線程ID設置爲當前使用的線程ID值。

 

3. ReleaseMutex:將互斥對象所有權進行釋放,交還給系統。

 

可以將互斥對象想象成一把鑰匙,CreateMutex創建了這把鑰匙,WaitForSingleObject等待這把鑰匙去訪問一個公共的資源,比如一個房間,如果擁有了鑰匙,則這個房間的所有權就屬於這個進程了,別人是進不去這個房間的,直到進程將這個房間的鑰匙歸還掉,即ReleaseMutex。


訪問控制項 (ACE)
安全描述符 (SD)
隨機訪問控制列表 (DACL)

 

當允許訪問的 ACE 被添加到文件的隨機訪問控制列表 (DACL) 中時,相應用戶或組帳戶與 ACE 關聯將由提供與該文件允許訪問系統。大多數的情況文件的 DACL 不足夠大,以添加更多的 ACE。因此,就需要創建一個新的訪問控制列表 (ACL) 和從該文件的現有 DACL 按首選順序複製ace。新的 DACL 然後可以替換該文件的安全描述符 (SD) 中舊的 DACL。

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