윈도우 커널 모드 포팅의 정석 7편 - 시간 함수 구현

저작권 안내
  • 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
  • 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.

포팅 작업을 할 때 의외로 중요한 부분이 시간에 관련된 부분입니다. 별것 아닌것 같지만 특정 시간 주기로 루틴이 실행된다던가, 데이터에 시간이 포함된다면 시간 함수 처리를 잘못하면 포팅을 하고 나서도 제대로 동작이 되지 않을 때가 많습니다.

먼저 포팅에 앞서 유저 모드와 커널 모드의 시간 처리 기준에 대해 이해할 필요가 있습니다.

  • 유저 모드 : 밀리초, 100나노초
  • 커널 모드 : 100나노초

따라서 유저 모드와 커널 모드의 처리 기준이 다르다면 변환이 필요합니다. 하지만 대부분의 시간 함수는 변환 없이 사용할 수 있습니다. 이 변환기준은 대부분 동기화 객체의 대기 타임아웃 처리 정도에 사용됩니다.

typedef struct _FILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;

void GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
{
    KeQuerySystemTime((PLARGE_INTEGER)&lpSystemTimeAsFileTime);
}

FILETIME과 같은 64비트 형태의 시간 구조체는 100나노초 단위입니다. 커널 모드에서도 64비트 형태의 LARGE_INTEGER 구조체를 사용하고 있으므로 변환 절차 없이 바로 사용할 수 있습니다.

typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

void GetSystemTime(LPSYSTEMTIME lpSystemTime)
{
    LARGE_INTEGER systemTime;
    TIME_FIELDS timeFields; 

    KeQuerySystemTime(&systemTime);

    RtlTimeToTimeFields(&systemTime, &timeFields);
}

SYSTEMTIME 구조체와 같이 연,월,일, 시, 분, 초, 요일을 세분화 한 것은 먼저 64비트 형식의 시간을 구한 다음 RtlTimeToTimeFields과 같은 함수로 변환해주면 됩니다.

#include <time.h>

errno_t localtime_s(struct tm * _Tm, const time_t * _Time)
{
    LARGE_INTEGER systemTime, localTime;
    TIME_FIELDS timeFields;

    KeQuerySystemTime(&systemTime);
    ExSystemTimeToLocalTime(&systemTime, &localTime);

    RtlTimeToTimeFields(&localTime, &timeFields);

    _Tm->tm_sec = timeFields.Second;
    _Tm->tm_min = timeFields.Minute;
    _Tm->tm_hour = timeFields.Hour;
    _Tm->tm_mday = timeFields.Day;
    _Tm->tm_mon = timeFields.Month;
    _Tm->tm_year = timeFields.Year;
    _Tm->tm_wday = timeFields.Weekday;

    return 0;
}

WinAPI가 아닌 CRT 함수의 경우 해당 CRT 함수의 구조체에 맞게 필드를 채워주어야 합니다. 먼저 64비트 형태의 시간을 구한 다음 ExSystemTimeToLocalTime 함수를 이용하여 로컬 타임으로 변환합니다. 그리고 RtlTimeToTimeFields으로 연,월,일... 형태로 변환한 뒤 tm 구조체에 맞게 값을 채워줍니다.

관련글


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

2009-08-09