윈도우 운영체제는 다양한 형태의 커널 개체를 생성하고 조작하고 종료 합니다. 프로그래머는 윈도우 운영체제에서 여러 가지 함수를 통해서 다양한 커널 개체를 만들 수 있습니다. 그러면 윈도우 운영체제는 커널에 메모리를 할당해서 커널 개체를 만듭니다. Windows 커널 모드 개체 관리자 구성 요소는 개체를 관리 합니다 . 파일, 장치, 동기화 메커니즘, 레지스트리 키 등은 모두 커널 모드에서 개체로 표시됩니다. 각 개체에는 정보가 표시되는 Header와 Body로 구성되어 있습니다. 프로그래머는 핸들 값을 얻어다가 참조를 통해서만 개체를 사용할 수 있습니다. 그래서 개체를 참조하여 사용자 모드에서 핸들을 가져올 수 있습니다. 개체를 참조하여 핸들을 가져오는 방식은 커널 개체를 생성하는 함수를 호출하면 함수는 개체를 식별 하는 핸들을 반환 합니다.
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
MICROSOFT DOCS
다음과 같이 커널 개체를 생성하는 함수는 프로세스별로 고유한 HANDLE을 return 해서 사용할 수 있습니다.
#include
#include
#define MAX_SEM_COUNT 10
#define THREADCOUNT 12
HANDLE ghSemaphore;
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(
NULL, // default security attributes
MAX_SEM_COUNT, // initial count
MAX_SEM_COUNT, // maximum count
NULL); // unnamed semaphore
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and semaphore handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
return 0;
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
https://docs.microsoft.com/
커널 개체를 생성하다 실패하면 반환하는 값은 nullptr이다. 거의 실패하지 않고 시스템의 가용 메모리가 작거나 기존의 코드와 호환이 되지 않는 보안문제가 있는 코드라면 그럴 수 있다고 한다. 때로는 INVALID_HANDLE_VALUE를 return 하기도 해서 확인할 때 두 가지 경우 모두를 고려해야 한다. 예를들면 CreateMutex는 호출이 실패하면 nullptr이 반환되고 CreateFile이 호출이 실패하면 INVALID_HANDLE_VALUE를 return 한다.