Windows Kernel Object 윈도우 커널 오브젝트

윈도우 커널 오브젝트에 관한 정리

Posted by Start Bootstrap on May 01, 2019

Windows Kernel Object

윈도우 운영체제는 다양한 형태의 커널 개체를 생성하고 조작하고 종료 합니다. 프로그래머는 윈도우 운영체제에서 여러 가지 함수를 통해서 다양한 커널 개체를 만들 수 있습니다. 그러면 윈도우 운영체제는 커널에 메모리를 할당해서 커널 개체를 만듭니다. 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 한다.