Windows OS2009. 3. 30. 23:53
반응형

유저모드 프로그램과 커널모드 드라이버간에 동기화가 필요할 때 막연히 Named Mutex 를 쓰면 된다고 생각했는데 막상 하려고 하니 막막하다.

Named Event 는 IoCreateNotificationEvent() 나 IoCreateSynchronizationEvent() 를 사용하면 되는데 커널모드에서 Named Mutex 를 오픈하는 커널 API 는 없는 것이었다.

한참을 헤메고 물어물어 발견한 방법은 ObOpenObjectByName() 으로 여는 방법이다. 다음과 같이 사용하면 된다. 유저모드 에서는 CreateMutex() 로 만들고 커널모드에서는 아래와 같이 만든다.
( 유저모드에서 사용한 Mutex 이름은 Global\\MyLockName 이다. )

NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes, POBJECT_TYPE ObjectType, PVOID ParseContext, KPROCESSOR_MODE AccessMode, ACCESS_MASK DesiredAccess, PACCESS_STATE PassedAccessState, PHANDLE Handle);

//
// 뮤텍스 초기화
//

UNICODE_STRING usLockName;
OBJECT_ATTRIBUTES stObjAttr;
HANDLE hLock = NULL;
PVOID pObject = NULL;

RtlInitUnicodeString( &usLockName, L"\\BaseNamedObjects\\Global\\MyLockName" );
InitializeObjectAttributes( &stObjAttr, &usLockName, OBJ_CASE_INSENSITIVE, NULL, NULL );

// Named Object 를 연다.
ntStatus = ObOpenObjectByName( &stObjAttr, NULL, NULL, KernelMode, 0, NULL, &hLock );
if (FALSE == NT_SUCCESS(ntStatus))
{
    return ntStatus;
}

// 핸들로부터 오브젝트 포인터를 구한다.
ntStatus = ObReferenceObjectByHandle( hLock, SYNCHRONIZE, NULL, KernelMode, &pObject, NULL );
if (FALSE == NT_SUCCESS(ntStatus))
{
   ZwClose( hLock );
   return ntStatus;
}

// 이제 핸들은 필요없으므로 닫는다.
ZwClose( hLock );


//
// 뮤텍스 사용
//

#define TIMER_100NANO_BASE 10000 // 1ms 계산용

LARGE_INTEGER lnTimeout;

// 타임아웃 시간설정
lnTimeout.QuadPart = dwMilliseconds * TIMER_100NANO_BASE;
lnTimeout.QuadPart = -lnTimeout.QuadPart;

// 동기화 뮤텍스를 얻기 위해 대기한다.
ntStatus = KeWaitForSingleObject( pObject, Executive, KernelMode, TRUE, &lnTimeout );
if (STATUS_SUCCESS != ntStatus)
{
  return ntStatus;
}

// 동기화가 필요한 작업을 여기서 한다.
// do something

// 뮤텍스의 소유를 해제한다.
KeReleaseMutex( pObject, FALSE );


//
// 뮤텍스 해제
//

ObDereferenceObject( pObject );

반응형
Posted by GreeMate