刘收获

导航

互斥体(用户模式 内核模式 快速互斥体)

一.用户模式互斥体  

  创建互斥体:

  HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes,   // pointer to security attributes
                     
    BOOL bInitialOwner,     //始化时是否被占有
    LPCTSTR lpName       // pointer to mutex-object name
       );

 

  释放互斥体:

  BOOL ReleaseMutex(
      HANDLE hMutex   // handle to mutex object
  );

 

  代码内容:获得了互斥体之后,同一个线程中可以递归获得互斥体,就是得到互斥体的线程还可以再次获得这个互斥体,或者说互斥体对于已经获得互斥体的线程不产生”互斥”关系。

 

  

// Mutex-ThreadSynchronization.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
//获得互斥体的线程不产生"互斥"关系(不互斥自己)
DWORD WINAPI ThreadProcedure(LPVOID ParameterData);
int main()
{
	HANDLE ThreadHandle[2] = {0};
	int i;

	HANDLE
	MutexHandle = CreateMutex(
		NULL,            
		FALSE,  //表明初始化时是否被占有          
		NULL);            

	if (MutexHandle == NULL)
	{
		printf("CreateMutex() Error\r\n");
		goto Exit;
	}
	for (i = 0; i < 2; i++)
	{
		ThreadHandle[i] = CreateThread(
			NULL,      
			0,         
			(LPTHREAD_START_ROUTINE)ThreadProcedure,
			(PVOID)&MutexHandle,       
			0,         
			NULL); 

		if (ThreadHandle[i] == NULL)
		{
			printf("CreateThread() Error\r\n");
			goto Exit;
		}
	}
	WaitForMultipleObjects(2, ThreadHandle, TRUE, INFINITE);
	for (i = 0; i < 2; i++)
		CloseHandle(ThreadHandle[i]);
Exit:
	{
		if (MutexHandle!=NULL)
		{
			CloseHandle(MutexHandle);
			MutexHandle = NULL;
		}
	}
	return 0;
}

DWORD WINAPI ThreadProcedure(LPVOID ParameterData)
{
	HANDLE MutexHandle = *((HANDLE*)ParameterData);
	DWORD Looping = 0;
	BOOL  IsOk = 0;
	
	//占有几次就必须解锁几次
	while (Looping < 5)
	{
		//占有互斥体
		IsOk = WaitForSingleObject(
			MutexHandle,
			INFINITE);   
		IsOk -= WAIT_OBJECT_0;
		switch (IsOk)
		{
		case WAIT_OBJECT_0:    //等待的对象变为已通知状态,那么返回值是WAIT_OBJECT_0。
		{
			__try {

				printf("ThreadID:%d\r\n",
					GetCurrentThreadId());
				Looping++;
			}

			__finally {

				//释放互斥体
				if (!ReleaseMutex(MutexHandle))
				{

				}
			}
			break;
		}
		case WAIT_ABANDONED:
			return FALSE;
		}
	}

	printf("ThreadProcedure() Exit\r\n");
	return TRUE;
}

  

二.内核模式互斥体

  

  1.互斥体在内核模式下的结构体KMUTEX,使用前需要进行初始化KeInitializeMutex,释放互斥体使用KeReleaseMutex内核函数

  2.PsCreateSystemThread创建新的线程占用互斥体

  3.ObReferenceObjectByHandle将句柄转化为指向object的指针,交给  KeWaitForMultipleObjects函数,用于同时等待一个或多个同步对象。

 

  NTKERNELAPI
  NTSTATUS
  KeWaitForMultipleObjects (
    _In_ ULONG Count,                                                                  //数组中指针的个数
    _In_reads_(Count) PVOID Object[],                                       //指向一个指针数组
    _In_ _Strict_type_match_ WAIT_TYPE WaitType,             //等待所有对象都进入信号态
    _In_ _Strict_type_match_ KWAIT_REASON WaitReason,
    _In_ __drv_strictType(KPROCESSOR_MODE/enum _MODE,__drv_typeConst) KPROCESSOR_MODE WaitMode,
    _In_ BOOLEAN Alertable,
    _In_opt_ PLARGE_INTEGER Timeout,
    _Out_opt_ PKWAIT_BLOCK WaitBlockArray
);

 

#include <ntifs.h>

VOID SeCreateMutex();
VOID ThreadProcedure(PVOID ParameterData);
VOID DriverUnload(PDRIVER_OBJECT DriverObject);


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
	NTSTATUS Status = STATUS_SUCCESS;

	PDEVICE_OBJECT  DeviceObject = NULL;

	DriverObject->DriverUnload = DriverUnload;


	SeCreateMutex();
	return Status;
}


VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("DriverUnload()\r\n");
}

VOID SeCreateMutex()
{
	KMUTEX  Mutex;
	HANDLE  ThreadHandle[2] = { 0 };
	ULONG   i = 0;
	PVOID   ThreadObject[2] = { 0 };
	KeInitializeMutant(&Mutex, 0);
	for (i = 0; i < 2; i++)
	{
		PsCreateSystemThread(&ThreadHandle[i], 0, NULL, NULL, NULL, ThreadProcedure, &Mutex);
	}
	for (i = 0; i < 2; i++)
	{
		//把线程句柄转换为可以等待的指针
		ObReferenceObjectByHandle(ThreadHandle[i], 0, NULL, KernelMode, &ThreadObject[i], NULL);
	}
	//等待2个新建线程执行完毕
	KeWaitForMultipleObjects(
		2,              //数组中指针的个数
		ThreadObject,   //指向一个指针数组
		WaitAll,        //等待所有对象都进入信号态
		Executive, 
		KernelMode, 
		FALSE, 
		NULL, 
		NULL);
	for (i = 0; i < 2; i++)
	{
		ObDereferenceObject(ThreadObject[i]);
		ZwClose(ThreadHandle[i]);
		ThreadHandle[i] = NULL;
	}
}
VOID ThreadProcedure(PVOID ParameterData)
{
	PKMUTEX Mutex = (PKMUTEX)ParameterData;
	int i = 0;

	//占有几次解锁几次
	for (i=0;i<3;i++)
	{
		KeWaitForSingleObject(Mutex, Executive, KernelMode, FALSE, NULL);

		//该函数是以微秒为单位
		KeStallExecutionProcessor(10000); //0.01秒	

		DbgPrint("ThreadID:%d\r\n",PsGetCurrentThreadId());

	  	KeReleaseMutex(Mutex, FALSE);
	}
	PsTerminateSystemThread(STATUS_SUCCESS);

	//当线程退出Mutex就不起作用了即使不解占有
}

  

三.快速互斥体

  快速互斥体是DDK提供的另外一种内核同步对象,他的特征类似于前面介绍的普通互斥体。他们两的作用完全一样,之所以被称为是快速互斥体,是因为它执行的速度比普通的互斥体速度快(这里指的是获取和释放的速度)。然而,快速互斥体对象不能被递归获取

  普通互斥体在内核中用KMUTEX数据结构表示,而快速互斥体在内核中用FAST_MUTEX数据结构描述。

除此之外,对快速互斥体的初始化,获取和释放对应的内核函数也和普通互斥体不同

 

  初始化:
  VOID 
        ExInitializeFastMutex(
        IN PFAST_MUTEX  FastMutex
      );
  获取:
  VOID 
    ExAcquireFastMutex(
      IN PFAST_MUTEX  FastMutex
       );
  释放:
  VOID 
    ExReleaseFastMutex(
         IN PFAST_MUTEX  FastMutex
     );

#include <ntifs.h>
VOID SeCreateFastMutex();
VOID ThreadProcedure(PVOID ParameterData);
VOID DriverUnload(PDRIVER_OBJECT DriverObject);


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_OBJECT  DeviceObject = NULL;
	DriverObject->DriverUnload = DriverUnload;
	SeCreateFastMutex();
	return Status;
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("DriverUnload()\r\n");
}
VOID SeCreateFastMutex()
{
	HANDLE  ThreadHandle[2] = { 0 };
	FAST_MUTEX  Mutex;
	ULONG   i = 0;
	PVOID   ThreadObject[2] = { 0 };

	ExInitializeFastMutex(&Mutex);

	for (i = 0; i < 2; i++)
	{
		PsCreateSystemThread(&ThreadHandle[i], 0, NULL, NULL, NULL, ThreadProcedure, &Mutex);
	}
	for (i = 0; i < 2; i++)
	{
		ObReferenceObjectByHandle(ThreadHandle[i], 0, NULL, KernelMode, &ThreadObject[i], NULL);
	}
	KeWaitForMultipleObjects(2, ThreadObject, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
	for (i = 0; i < 2; i++)
	{
		ObDereferenceObject(ThreadObject[i]);
		ZwClose(ThreadHandle[i]);
		ThreadHandle[i] = NULL;
	}
}

VOID ThreadProcedure(PVOID ParameterData)
{
	PFAST_MUTEX  Mutex = (PFAST_MUTEX)ParameterData;;
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		ExAcquireFastMutex(Mutex);
		//该函数是以微秒为单位
		KeStallExecutionProcessor(10000); //0.01秒	
		DbgPrint("ThreadID:%d\r\n", PsGetCurrentThreadId());
		ExReleaseFastMutex(Mutex);        //如果当前线程不解锁就互斥住自己

	}
	PsTerminateSystemThread(STATUS_SUCCESS);
}

  

posted on 2017-08-15 13:45  沉疴  阅读(665)  评论(0编辑  收藏  举报