콘솔 프로그램에서의 SetTimer :: 2007/07/08 19:12



몇 일 전 콘솔 프로그램에서 타이머를 사용하는 프로그램을 작성할 일이 있었습니다. SetTimer 함수에 첫 번째 인자를 NULL로 넣으면 메시지로 날라오지 않고 콜백으로 동작하죠. 그래서 당연히 그렇게하면 콘솔 프로그램에서도 사용할 수 있다고 생각했습니다. 왠걸. 타이머 콜백이 호출이 되질 않는 것입니다. 코드를 고쳐가며 쌩 쑈를 해보았지만 안되었습니다. 그러다 포기하고 구글님에게 물으러 갔죠.

INFO: SetTimer() Should Not Be Used in Console Applications

구글님은 역시나 저를 실망시키지 않았습니다. 내용의 요는 SetTimer가 동작하기 위해서는 메시지 루프를 포함하고 있어야 한다는 것 입니다. 그동안 저는 SetTimer가 그냥 커널에서 계산해서 호출해 주는 정도로 알고 있었는데, 그게 아니었나 봅니다. 그래서 ReactOS 홈페이지에서 관련 소스를 한번 찾아봤습니다.

ReactOS
ReactOS는 윈도우 클론을 만들어 보자는 취지의 오픈 소스 프로젝트입니다. 그래서 윈도우의 중요한 코어 부분을 직접 구현하는 작업을 하고 있죠. 굉장한 작업이죠. 공개가 하나도 되지 않은 윈도우 운영체제를 리버싱해서 똑같은 것을 만드는 일이니까요. 그런데 참 신기한 사실은 몇 해전 유출되었던 윈도우 2000의 소스 코드와 ReactOS의 소스 코드가 굉장히 유사하다는 점 입니다. 비 공개된 커널 구조체의 필드명 같은 것들 말이죠. 함수명도 마찬가지 입니다. 그 원인이야 어찌됐는 저희한테는 쌩큐죠. 윈도우 소스 코드를 홈페이지를 통해서 볼 수 있으니 말이죠. 저도 예전 유출되었던 윈도우 소스 코드를 ctag으로 만들어서 보곤 했는데 doxygen으로 작업된 것이 백만배 정도는 더 편리 하더군요.

전체적인 함수의 흐름은 다음과 같습니다. 마지막 함수를 보면 삘이 확 오죠. ㅋ
SetTimer -> NtUserSetTimer -> IntSetTimer -> MsgSetTimer

MsgSetTimer 함수의 핵심 부분은 아래와 같이 구현되어 있습니다. 타이머가 발생해야 하는 시간을 현재 시간 기준으로 계산하고 그 타이머 객체를 메시지 큐에 추가하는 것이 전부죠. 이제야 왜 SetTimer에 메시지 큐가 필요한지 이해가 되죠. 돌이켜 생각해 보니 바쁜 커널이 모든 타이머를 일일히 호출해 주는 건 정말 쓸데없는 짓인것 같네요.


콘솔 프로그램에서 메시지 큐 없이 SetTimer를 써야 한다면 위 글에서 나와있는대로 멀티미디어 타이머를 사용하는 방법이 있습니다. 그것도 여의치 않다면 별도의 스레드에서 직접 호출해 주는 방법 밖에는 없습니다. 그런데 이 때 한 가지 주의 해야 할 점은 멀티미디어 타이머든 자신이 직접 만든 스레드에서 호출하든 이 것들은 원래 스레드 컨텍스트에서 호출되지 않는다는 점 입니다. 따라서 타이머 프로시저가 공유 자원에 접근하는 경우라면 동기화에 신경을 써야 합니다.

스폰서
글타래

  • 2주간 인기 글
  • 2주간 인기글이 없습니다.
Trackback Address :: http://jiniya.net/tt/trackback/533
  • Gravatar Image.
    snaiper | 2007/07/08 20:07 | PERMALINK | EDIT/DEL | REPLY

    MVP 3년만 꾸준히 유지하면, 그 소스 안봐도 원래의 소스 볼 수 있는데 말이지.
    예전에 윈도 소스 봤을 때, 특히나 IIS 소스는 고뇌의 코드임을 절실히 느낄 수 있었다는 ^^:

    • Gravatar Image.
      codewiz | 2007/07/08 23:35 | PERMALINK | EDIT/DEL

      글에서 제시된 것처럼 소스가 별반 차이가 없다는게 MVPSLP가 큰 메리트가 없는 점입니다. 제가 참고한 ReactOS 소스야 어차피 공개 소스이기 때문에 상관이 없지만 제가 MVPSLP를 통해서 참고하고 이런 글을 쓴다면 사실 뒷통수가 좀 가렵죠. *^^*

      그리고 제가 신청을 해본 적이 없어서 정확히는 모르겠지만 홈페이지 상에는 3년이란 규정은 없습니다. 신청하고 심사만 통과하면 처음으로 MVP가 된 사람도 볼 수 있는 것 갈네요. 18세 이상이란 규정이 좀 재밌군요. 윈도우 코드는 미성년자 관람 불가란 말인가 ㅋㅋ

      Eligibility requirements
      Maintain status as a Microsoft MVP in good standing.
      Reside in an eligible geographic market. The MVPSLP is available to MVPs residing in Australia, Austria, Belgium, Bulgaria, Canada, Cyprus, the Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Japan, Latvia, Lithuania, Luxembourg, Malta, the Netherlands, New Zealand, Norway, Poland, Portugal, Slovakia, Slovenia, South Korea, Spain, Sweden, Switzerland, the United Kingdom, and the United States.
      Be 18 years of age or older.
      Sign the Master Source Code Agreement (MSCA) and the License Form.

      하지만 늘 그렇듯이 진짜를 보는데는 많은 제약이 따릅니다. 규정도 많죠. 잘못 관련 자료를 발설했다간 ㄷㄷㄷ...

    • Gravatar Image.
      snaiper | 2007/07/09 01:21 | PERMALINK | EDIT/DEL

      하긴 SetTimer 정도는 메리트가 없을 수 있겠네..

      나는 주로 2000 소스 유출시도 안 나온
      IIS 라던지 Windows 로그인 쪽이라던지 뭐
      이런 것만 봐서 그런가..

      그리고 3년 얘기는 예전부터 있었어...요새는 몰겠는데
      3년이 안되면 자격 조건이 안된다고 그러고...

      근데 설사 그렇다고 하더라도 소스만 안밝히고 순서 정도만 밝히는 건 상관없지 않나? 라이선스 좀 애매하네... Windows Internal 같은걸 볼 때 가능할 것 같기도 하고...

  • Gravatar Image.
    rockenrollz | 2007/07/08 21:41 | PERMALINK | EDIT/DEL | REPLY

    MVP 3년하면 그런것도 볼수 있어요???

    • Gravatar Image.
      codewiz | 2007/07/08 23:37 | PERMALINK | EDIT/DEL

      MVPSLP란 프로그램이 있어. MVP Source Licensing Program의 약자로 주요 윈도우 운영체제의 소스 코드를 볼 수 있지. 근데 98 소스는 없어 ㅋㅋㅋㅋ

  • Gravatar Image.
    정성태 | 2007/07/09 16:04 | PERMALINK | EDIT/DEL | REPLY

    MVP 3년 규정은 예전에 있었던 것입니다.
    그거 폐지된지 2~3년 된 것 같습니다.

    신청 방법은 매우 쉽습니다. MVP 쪽 SharedSource 팀에 신청의사를 밝히면 그쪽에서 NDA 서약서를 보내줍니다. 그거에 서명해주고 보내면, SmartCard 한장을 보내주는 데 그걸로 접속이 가능합니다. ^^

    재미있는 것은, 공유소스 접근과 PDB Symbols 만 구성되면 Windows 응용 프로그램 디버깅 시에 직접 윈도우즈 소스 코드 수준의 디버깅까지 가능하다는 것입니다.
    이에 대해서는 다음의 토픽에 써놓았으니 참고하십시오. ^^

    CCP 를 이용한 Windows Source Code 수준의 디버깅
    ; http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&detail=1&wid=325

    • Gravatar Image.
      codewiz | 2007/07/09 16:27 | PERMALINK | EDIT/DEL

      좋은 정보 감사합니다. 한 번도 신청해 본적이 없어서 잘 몰랐네요. 그나저나 윈도우즈 소스 코드 수준의 디버깅이 가능하다는 것은 생각해보지 않았는데 정말 큰 메리트가 될 것 같네요. ㅎㅎ

    • Gravatar Image.
      snaiper | 2007/07/09 17:32 | PERMALINK | EDIT/DEL

      아 3년 규정 없어졌군요. 그건 좋은데요..그럴 줄 알았으면 작년에 신청해둘껄 그랬네요

  • Gravatar Image.
    kkamagui | 2007/07/17 16:37 | PERMALINK | EDIT/DEL | REPLY

    오~ 글 잘봤습니다. 그런데 얼핏 이해가 안되는 부분이 있네요.

    "이 때 한 가지 주의 해야 할 점은 멀티미디어 타이머든 자신이 직접 만든 스레드에서 호출하든 이 것들은 원래 스레드 컨텍스트에서 호출되지 않는다는 점 입니다."

    이 부분인데... 멀티미디어 타이머는 제가 잘 안써봐서 모르겠는데, 일반 타이머 같은 경우는 메시지 큐에서 퍼와서 타이머를 처리하니까 원래 스레드 컨텍스트에서 호출 되는거 아닌가요?

    뭔가 다른곳에서 호출한다는 그런 뉘앙스가 조금 있는 것 같은데... ^^;;;;;


    • Gravatar Image.
      codewiz | 2007/07/17 17:05 | PERMALINK | EDIT/DEL

      네 일반 타이머는 당연히 같은 스레드 컨텍스트에서 호출됩니다.
      멀티미디어 타이머, 자신이 직접 만든 스레드에서 호출하는 타이머를 만든 경우에 컨텍스트가 달라진다는 이야기입니다. 직접 별도의 스레드로 타이머를 제작하는 경우에 동일한 스레드에서 콜백을 호출하도록 하는 것은 굉장히 힘든 일이더군요.

Name
Password
Homepage
Secret