Microsoft Developer Network > 포럼 홈 > Visual Basic > 請問 GetTickCount() 是準的嗎?
질문하기질문하기
 

답변됨請問 GetTickCount() 是準的嗎?

  • 2007년 11월 26일 월요일 오전 7:27dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    GetTickCount() 由線上說明可以知道,它是取得自系統啟動到目前的時間,以毫秒為單位。使用 GetTickCount() 作一般計時,算是很常用的應用,也有一些軟體使用 GetTickCount() 及目前時間去反推系統啟動的時間。

    我目前遇到的問題是這樣子的:
    # 電腦使用 Mobile 的 CPU。
    # 我的系統每 0.5 秒會記一筆資料到檔案,同時把當時的時間及 GetTickCount() 值也一併記下。
    # 系統在 IDLE 無人操作時,不知道什麼原因,會發生時間自動調快 1~2 分鐘,但前後筆資料的 GetTickCount() 值是連續的,也就是只有差 0.5 秒。例如:

    記錄時間          GetTickCount
    17:53:23.062    21,598,625
    17:53:23.562    21,599,125
    17:53:24.062    21,599,625
    17:55:32.562    21,600,125
    17:55:33.062    21,600,625
    17:55:33.562    21,601,125

    在 17:53:24.062 直接跳到 17:55:32.562 但 GetTickCount 的差值是 500 (ms)

    由記錄上看,在無人操作時,此跳動時間每小時會發生一次,每次跳 2 分鐘左右。

    是否 GetTickCount 在每台電腦上執行的速度不太一樣,可能有些電腦取得的 Count 數的真實時間單位是 1ms
    但有些可能多一點點或少一點點,如 1.001 ms 而每秒多 1ms 或是 .999 ms 每秒少 1ms 如果累積的一定程度,
    與 BIOS Real Time Clock 的差異就變大。
    也就是我的問題,即 GetTickCount 是準的嗎?

    如果 GetTickCount 不準會怎樣?
    是否有可能是 Windows 系統本身會去判斷系統時間與 BIOS Real Time Clock 差太多時,會自動調整時間?

답변

  • 2007년 11월 26일 월요일 오전 8:01璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     답변됨

    這邊有一篇你可以看看中斷時間跟硬體的關係,包含裡面黑暗執行緒那篇連結也看看:

    http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!1640.entry

     

    你這個問題,我建議你檢查那台電腦是否有自動校時程式,比如說 ntpclock ,這個應該是被程式或指令直接設定時間,所以時間有變化而計數器正常。

     

    電腦時間的精度與解析度的詳細探討在上面網址有說明了,這邊只重覆描述 MSDN 上的說明,GetTickCount 在 Win9x 下解析度是 54ms ,在 WinNT 下是 10ms ,10 ms 以下的是主機板的能耐,所以 GetTickCount 是在粗解析度下,執行效能最快的函式。

     

    GetTickCount 不準的話,應該是你主機板上的頻率震盪器有問題,或是水銀電池快沒電了,那個要問主機板廠商,通常會叫你寄回維修,一搞就要兩周。

     

    作業系統不會主動調時,所以通常為校時程式,加入 AD 的話,會定時向 AD Server 校時 (下對上),當然若是管理員有特別寫定時校時程式,也可以由上對下強迫更新時間。

  • 2007년 11월 26일 월요일 오후 1:29cmfMVP사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     답변됨

    DLLEE 大大:

    這有點難度  

    只能提供資料 給你參考

    CALL 中斷為小的時間增量使用 BIOS 滴答計數

    http://support.microsoft.com/kb/57851/zh-tw

    使用中斷 15 十六進位為時間遞增小於 1 秒


    http://support.microsoft.com/kb/65927/zh-tw

모든 응답

  • 2007년 11월 26일 월요일 오전 8:01璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     답변됨

    這邊有一篇你可以看看中斷時間跟硬體的關係,包含裡面黑暗執行緒那篇連結也看看:

    http://tlcheng.spaces.live.com/blog/cns!145419920BFD55A7!1640.entry

     

    你這個問題,我建議你檢查那台電腦是否有自動校時程式,比如說 ntpclock ,這個應該是被程式或指令直接設定時間,所以時間有變化而計數器正常。

     

    電腦時間的精度與解析度的詳細探討在上面網址有說明了,這邊只重覆描述 MSDN 上的說明,GetTickCount 在 Win9x 下解析度是 54ms ,在 WinNT 下是 10ms ,10 ms 以下的是主機板的能耐,所以 GetTickCount 是在粗解析度下,執行效能最快的函式。

     

    GetTickCount 不準的話,應該是你主機板上的頻率震盪器有問題,或是水銀電池快沒電了,那個要問主機板廠商,通常會叫你寄回維修,一搞就要兩周。

     

    作業系統不會主動調時,所以通常為校時程式,加入 AD 的話,會定時向 AD Server 校時 (下對上),當然若是管理員有特別寫定時校時程式,也可以由上對下強迫更新時間。

  • 2007년 11월 26일 월요일 오전 9:21dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    感謝璉璉大大的回覆。

    您提供的資料我看過了,對於 GetTickCount 及 QueryPerformanceFrequency/QueryPerformanceCounter 函式也都清楚它們的用法了,謝謝您提供的資料。

    目前的系統只有安裝 Windows XP Pro SP2 及我的程式,沒有自動對時的程式,也把 Windows XP 內建的網路對時功能關閉了,但是還是會發生類似的狀況。

    如果作業系統不會主動調時間,那我有什麼方式可以知道是那個程式改了時間嗎?

    您提到 GetTickCount 不準可能是主機板的頻率震盪器有問題,或水銀電池沒電,此部分我會請 PC 廠商協助。
    另外想再請教您,是否按您的經驗(或您有讀過相關的資料) 是否在硬體沒有頻率震盪器或電池沒電的問題時,
    GetTickCount 就是準的呢?GetTickCount 的「來源」是硬體產生的嗎?當我們叫用此 API 時,系統是去那兒取來的值傳回給我們呢?

    不好意思... 我的問題比較多... 麻煩您了。
  • 2007년 11월 26일 월요일 오전 9:37璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     

    只是近似,所以才需要網路校時。

     

    早期的 GetTickCount 是直接從主機板上石英震盪器來的,到了 WinNT 怎樣做忘記了。

     

    我猜應該是透過 CPU 內計數器 / 頻率振盪器的頻率,定時寫入註冊檔,再提供給 GetTickCount 呼叫取得。

     

    這部分 API 的註解有寫:

    程式碼區塊

    Remarks

    The resolution is limited to the resolution of the system timer. This value is also affected by adjustments made by the GetSystemTimeAdjustment function.

    The elapsed time is stored as a DWORD value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days. To avoid this problem, use GetTickCount64. Otherwise, check for the overflow condition when comparing times. For more information, see the example below.

    If you need a higher resolution timer, use a multimedia timer or a high-resolution timer.

    To obtain the time elapsed since the computer was started, retrieve the System Up Time counter in the performance data in the registry key HKEY_PERFORMANCE_DATA. The value returned is an 8-byte value. For more information, see Performance Counters.

     

  • 2007년 11월 26일 월요일 오후 1:29cmfMVP사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     답변됨

    DLLEE 大大:

    這有點難度  

    只能提供資料 給你參考

    CALL 中斷為小的時間增量使用 BIOS 滴答計數

    http://support.microsoft.com/kb/57851/zh-tw

    使用中斷 15 十六進位為時間遞增小於 1 秒


    http://support.microsoft.com/kb/65927/zh-tw

  • 2007년 11월 26일 월요일 오후 2:55璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     

    在 WinNT 下,只有用 VC 開發的軟體可以呼叫中斷

  • 2007년 11월 26일 월요일 오후 3:00璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
     cmf 寫信:

    DLLEE 大大:

    這有點難度  

    只能提供資料 給你參考

    CALL 中斷為小的時間增量使用 BIOS 滴答計數

    http://support.microsoft.com/kb/57851/zh-tw

    使用中斷 15 十六進位為時間遞增小於 1 秒


    http://support.microsoft.com/kb/65927/zh-tw

     

    關於這兩篇網址內談到的時間解析度可以參考前面貼的網址,在華碩的主機板上可以獲得更高的時間解析度,等同 CPU 頻率。

  • 2007년 11월 26일 월요일 오후 3:45cmfMVP사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
     璉璉 寫信:

    在 WinNT 下,只有用 VC 開發的軟體可以呼叫中斷



    璉 大:

    應該是  VC 開發的 驅動程式 才能 直接 呼叫硬體中斷 吧  ?

    ===================================================

    我想的是 這樣

    硬體中斷 -----> 驅動程式 <------->  DLL <--------> APPLICATION




  • 2007년 11월 27일 화요일 오전 5:52dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    感謝 cmf 大大及 璉璉大大的回覆。
    目前我先向 PC 硬體廠商確認,是否 BIOS 或 Driver 有問題,或是電池等問題。
    我只擔心,可能這個問題只有我會發生,原廠也查不出原因。

    按 cmf 及 璉璉 大大的回應,結論應該是 GetTickCount() 的資料源是來自於電腦硬體。
    接下來我會測試我的程式不跑,是否也會發生跳時的狀況,作為原廠除錯的參考。
    再次感謝兩位的回覆。
  • 2007년 11월 28일 수요일 오후 1:26dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    對不起... 因為問題還沒解決, 所以還沒結案。
    我使用中華電信的網路對時程式,在一開機,先使用它更新系統時間與標準時間同步,接著把它自動調整時間改成手動,也就是只利用它來查標準時間。
    另外寫一個小程式,在啟動時,先以 GetTickCount 反推系統開機時間,
    再以 Timer 每秒讀取
    系統時間, GetTickCount, QueryPerformanceFrequency, QueryPerformanceCounter 等數值,與前次數值作比較,若發現系統時間變化大於 1.5 秒,則另外作記錄,實測如下圖:

    http://img411.imageshack.us/my.php?image=00155504kl4.png
    http://img411.imageshack.us/my.php?image=00163411fy0.png
    http://img214.imageshack.us/my.php?image=00164038ft7.png
    http://img214.imageshack.us/my.php?image=00164434ej5.png

    可以看到,在標準時間 16:40:38 時,系統時間已落後 145.699 秒。
    測試程式發現在系統時間從 16:41:12 直接跳到 16:43:49,可以看到 GetTickCount 的差值正好 1,000 但系統時間卻被(不知名的程式?服務?驅動程式?)調快 2.5 分鐘了,
    由標準時間 16:44:34 的貼圖可以看到,系統時間被調整後,與標準時間的差值變小了。

    今天持續找相關資料,這篇
    http://download.lenovo.com.cn/support/xiazaizx/BIOSsjcx/wqy2k06.html

            對于使用當前時間(時鐘)進行日期處理的應用程序來說,
            它所使用的電腦時鐘有三個:操作系統時鐘、BIOS時鐘和
            硬件實時時鐘RTC(Real Time Clock)。

            1) 操作系統時鐘在每次操作系統啟動時讀取BIOS時鐘獲得
               初始值,隨后操作系統通過將系統計數器的值轉換為時
               間數據來對它進行維護。操作系統啟動后,這兩個時鐘
               互相獨立地進行工作。
            2) BIOS時鐘在微機開機后才能運轉,其目的就是在微機剛
               啟動時讀取硬件實時時鐘(RTC)的時間值再向操作系
               統提供。
            3) 硬件實時時鐘RTC依靠電腦主板上的獨立電源(紐扣電池)
               供電,無論在開、關機狀態下它都在工作。
               對于絕大部分應用程序經常使用的是操作系統時鐘。

    目前這台電腦,好像就是系統時間愈來愈慢(但不是固定速度的慢,慢的速度似乎是浮動的),而不知道是什麼服務或是驅動程式,在偵測到系統時間與 BIOS 或 RTC 時間差太多時,就自動作了調整。

    之前璉璉大大有提到,系統不會去作時間的調整,只是目前我遇到的狀況,實在是不知道是那個程式或服務或驅動程式調了時間。

    P.S. 以上測試中,我已經把 Windows Time 服務關閉了,同時,日期時間的網路對時也取消勾選了。有使用中華電信的網路對時程式,但是是切手動的模式,只用來查標準時間。使用中華電信查標準時間只是為了由電腦中就可以作貼圖,不然,就要用數位相機來拍時鐘與畫面,但使用時鐘又可能有
    時鐘時間不準的問題,所以,還是使用查標準時間的方式來進行。
  • 2007년 11월 28일 수요일 오후 1:51璉璉MVP, 중재자사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     

    那不就是我一開始說的 ntpclock ?ntpclock 預設就是一小時校時一次。

     

    你圖上的數據滿奇怪的,系統頻率應該是不會變的,還是你有啟用動態節能的程式,會調節 cpu 運作頻率的那種?

     

    你盡量把不用的東西關閉,若分不出來的話,用安全模式加網路來測看看。

     

    另外把可以去抓 ProcessMonitor

    http://www.microsoft.com/taiwan/technet/sysinternals/utilities/processmonitor.mspx

     

    監測一段時間,看看那個時刻到底是誰動了時間,比如說若是小時鐘自動校時,是:

    程式碼區塊

    26128 下午 09:48:11.5960605 rundll32.exe 2844 RegOpenKey HKLM\System\CurrentControlSet\Services\W32Time\Parameters REPARSE 
    26129 下午 09:48:11.5960831 rundll32.exe 2844 RegOpenKey HKLM\System\CurrentControlSet\Services\W32Time\Parameters SUCCESS 
    26130 下午 09:48:11.5961077 rundll32.exe 2844 RegSetValue HKLM\System\CurrentControlSet\Services\W32Time\Parameters\NtpServer SUCCESS Type: REG_SZ, Length: 48, Data: time.stdtime.gov.tw,0x1
    26131 下午 09:48:11.5961185 rundll32.exe 2844 RegCloseKey HKLM\System\CurrentControlSet\Services\W32Time\Parameters SUCCESS 
    26132 下午

    ...

     

     

     

  • 2007년 11월 28일 수요일 오후 2:18dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    可是我在沒使用中華電信網路對時程式也關閉 Windows 日期時間的網路對時功能時,就會發生系統時間跳動的問題,會使用中華電信網路對時程式純粹是為了取得標準時間,請璉璉大大不要被我太多的貼圖搞混了。

    我使用的 CPU 是賽陽 Mobile 1G Hz 的 CPU,但是,我沒有安裝任何調節 CPU 運作的軟體。

    明天到公司再按您說的,以安全模式+網路的方式再跑跑看,希望時間不要再跳了...

    另外,您介紹的 Process Monitor 好像功能強大,但資訊好多喔...
    有什麼設定可以只查看與系統時間修改有關的就好?

    再次感謝您的回覆及建議。
  • 2007년 11월 28일 수요일 오후 2:47dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    http://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html
    這篇提到在 Windows Kernel 是會去讀取 BIOS RTC(Real Time Clock) 的,只是沒寫是一直讀還是只有開機讀。
  • 2007년 11월 29일 목요일 오전 1:53cmfMVP사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     

    HI  D 大:

     

    1: 您是用 TTimer  這元件  的  OnTimer 事件  每秒觸發 去 讀取 系統時間嗎

     

    2:  您時間的容許誤差 為 多少 ms

  • 2007년 11월 29일 목요일 오전 2:08dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    是的,用的是系統的 Timer。
    TTimer 也是叫用 SetTimer 攔 WM_TIMER 訊息,與任何語言的基本 Timer 是一樣的。

    對於時間,因為我是要量測機台運作時間,製程時間 1~3 分鐘不等,客戶會希望至少量測的運作時間,秒要準,但是目前是遇到系統時間「自動」跳,導致前後時間差被加大了。因為我是在運作中,每 0.5 秒就會送一筆資料,包含系統時間及所讀取的數值,
    給客戶的系統,客戶直接記錄到資料庫,事後再取出來看,發現有一段時間沒數值,同時,該批的生產總時間變過大,會被系統判定為異常批。
    ------------------
    今天早上把昨天測試機(關閉所有對時機制及服務)的狀況讀回,發現時間還是有跳動:

    Monitor Clock (2007-11-28)
    System Start Up Time   : 2007-11-28 15:41:13.000
    Current Time           : 2007-11-28 15:54:14.805
    GetTickCount           : 781,312
    PerformanceCounter     : 1,842,848,840
    ----
    Current Time           : 2007-11-28 16:43:49.828
    GetTickCount           : 3,600,468
    PerformanceCounter     : 9,522,432,349
    Last Time              : 2007-11-28 16:41:12.961
    Last GetTickCount      : 3,599,468
    Last PerformanceCounter: 9,516,405,067
    Time Shift Detected!!
    ----
    Current Time           : 2007-11-28 17:45:07.859
    GetTickCount           : 7,200,500
    PerformanceCounter     : 17,908,314,336
    Last Time              : 2007-11-28 17:43:48.859
    Last GetTickCount      : 7,199,500
    Last PerformanceCounter: 17,904,734,715
    Time Shift Detected!!
    ----
    Current Time           : 2007-11-28 23:46:16.859
    GetTickCount           : 28,800,500
    PerformanceCounter     : 67,641,317,592
    Last Time              : 2007-11-28 23:45:06.859
    Last GetTickCount      : 28,799,500
    Last PerformanceCounter: 67,637,745,875
    Time Shift Detected!!
    ----
    Current Time           : 2007-11-29 05:47:17.859
    GetTickCount           : 50,400,500
    PerformanceCounter     : 116,522,345,266
    Last Time              : 2007-11-29 05:46:15.859
    Last GetTickCount      : 50,399,500
    Last PerformanceCounter: 116,518,771,079
    Time Shift Detected!!
    ----

    以上可以發現一點與在客戶端的狀況
    一樣,感覺就是有一個以 1 小時為單位的 Timer,此 Timer 在發現系統時間與「真實」時間差大於 1 分鐘時,就會作一次調整。

    第1次:由 2007-11-28 16:41:12.961 下一秒應該是
    2007-11-28 16:41:13.961 變成 2007-11-28 16:43:49.828
    第2次:由 2007-11-28 17:43:48.859
    下一應該是 2007-11-28 17:43:49.859 成 2007-11-28 17:45:07.859
    第3次:由 2007-11-28 23:45:06.859
    下一應該是 2007-11-28 23:45:07.859 成 2007-11-28 23:46:16.859
    第4次:由 2007-11-29 05:46:15.859
    下一應該是 2007-11-29 05:46:16.859 成 2007-11-29 05:47:17.859
    此外,
    System Start Up Time   : 2007-11-28 15:41:13.000
    也正好是第一次時間跳動的整點差!!

    問題是,「誰」調整了時間?那個「誰」是去那兒取得「真實」時間?
    此測試系統在 第 1 次偵測到時間跳動時,我已把網路線拔除了,就算它內部有網路對時,也無法由網路查到時間,但是,時間還是跳動了,同時是往「標準」的時間跳。

    系統真的不會自己跳時間嗎?
  • 2007년 11월 29일 목요일 오전 2:28cmfMVP사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     

    D 大:

     

      WM_TIMER  MESSAGE  優先權很低喔   

     

    如下說明 

    程式設計人員很容易誤解視窗應用程式會中斷原先的工作轉而先處理WM_TIMER,然而與WM_PAINT訊息一樣WM_TIMER是一個低優先權的訊息,如果訊息佇列中還有其他訊息 WM_TIMER就會被暫時擱置,而且當佇列裡已經有WM_TIMER訊息尚未被處理又發生第二個第三個訊息,作業系統只會合併第二以及後續抵達的WM_TIMER訊息,佇列中仍只保留一個WM_TIMER訊息

     

     

    改用 Thread 來寫   看看 是否會改善

  • 2007년 11월 29일 목요일 오전 10:27dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    WM_TIMER 優先權很低沒有關係,您可以看到 Log 我是在 Timer 事件中再去讀取目前時間、GetTickCount 及 QueryPerformanceCounter 等,就算 WM_TIMER 不準,仍不影響我作判斷。
    目前主要是時間會瞬間跳動,這個問題比較大。
  • 2007년 12월 3일 월요일 오전 4:08dllee 사용자 메달사용자 메달사용자 메달사용자 메달사용자 메달
     
    在幾天下來的測試,已經發現,GetTickCount 是不準的,而且,依硬體的差異,可能會很不準。

    此外,在系統 BIOS 時間的部分,還是算準的,但進 Windows 後 Windows 時間只在一開機時取用 BIOS 時間,之後跑它自己的,使用查看 BIOS 時間的工具,發現 BIOS 時間是準的,但 Windows 時間就是比它慢。

    或許只有我用的硬體比較有問題... 已反應給硬體供應商,希望他們可以改善。

    再次感謝 璉璉大大 及 cmf 大大 提供的資料。