簡體   English   中英

在 C/C++ 中編寫計時器的最簡單方法是什么?

[英]What is the simplest way to write a timer in C/C++?

在 C/C++ 中編寫計時器的最簡單方法是什么?

你好,

用 C/C++ 說,編寫計時器的最簡單方法是什么? 以前我使用了 for 循環和 do-while 循環。 我使用 for 循環作為計數器,使用 do-while 循環作為“時間結束”的比較。 該程序按我的意願運行,但消耗了太多系統資源。

我正在尋找編寫計時器的最簡單方法。

謝謝!

編輯:

該程序適用於 Linux 和 Windows 的一組服務器,因此它是一個多平台環境。 我不想使用 unsleep 或 sleep 功能,因為我試圖從頭開始編寫所有內容。

程序的性質:該程序計算系統上的電源時間和電池時間。

編輯2:

好吧,這似乎引起了一些混亂,所以我將嘗試解釋到目前為止我所做的。 我創建了一個在后台運行的程序,如果系統閑置一段時間,它會關閉系統電源,它還檢查特定系統的電池壽命,如果系統一直在運行,它會進入待機模式電池一段時間。 我手動輸入時間,所以我需要一個計時器。 我想從頭開始編寫它,因為它是我一直在從事的個人項目的一部分。

最好的辦法是使用操作系統原語,在給定的時間內暫停程序(如 Windows 中的 Sleep())。 程序運行的環境很可能有一些機制來做這件事或類似的事情。 這是避免輪詢和消耗 CPU 時間的唯一方法。

如果你只是想讓你的程序等待一段時間,你可以使用:

  • 睡眠(在 Windows 中)
  • usleep(在 Unix 中)
  • boost::this_thread::sleep(無處不在)

如果您希望處理或顯示一直到過去的時間,您使用 while() 循環的方法很好,但您應該在while 循環,以免占用 CPU。

有兩種方式:

一。 編寫您自己的計時器來包裝特定於平台的命令。 並堅持使用它。 例如

void MySleep::Sleep(int milliSec)
{
#ifdef WIN32
   sleep(milliSec) ;
#else
#ifdef LINUX
   usleep(milliSec*1000); //microseconds
#endif
#endif
}

二。 選擇支持所有目標平台的庫和工具包。 Qt 和 boost 等工具包可用於掩蓋特定於平台的 goo。

boost 和 Qt 都有功能強大且可擴展的定時器。 我建議你查查它們。

http://linux.die.net/man/2/alarm

描述:
alarm() 安排在seconds秒鍾內將 SIGALRM 信號傳遞給進程。

並在 Windows 上使用 cygwin。

你已經在做的事情是最簡單的。

它消耗了太多的 CPU,因為它很難進行檢查(計時器是否已過期?)或其他什么。

為了解決這個問題,在主循環中放入 usleep(1) 或任何相當於一個非常短的睡眠的操作系統,你就會得到你需要的東西。

使用 sleep 函數.. 和函數指針

使用 sleep 函數不會消耗處理器時間......您可以使用函數指針來通知計時器何時到期。 如果您不需要事件,您可以簡單地使用睡眠/延遲功能

編輯按照 smallduck 的建議進行操作。 使用宏當前調用適當的操作系統調用(如果您想避免使用 boost)...使用其他任何東西,那么計時器將不准確。

您沒有提到您在其中構建計時器的環境。例如,微控制器通常有一個計時器/計數器單元,它通過計算時鍾周期以一定的時間間隔引發中斷,您可以只處理它們的中斷。

您可以多次調用 time() 並比較值。

#include <time.h>

int main ()
{
  time_t start_time;
  time_t current_time;

  start_time = time(NULL);
  current_time = time(NULL)

  while (current_time < start_time + TIMEOUT)
  {
  /* Do what you want while you're waiting for the timeout */
  current_time = time(NULL);
  }

 ...
}

與 sleep() 相比的優勢在於您仍然可以在等待時執行代碼。 例如...輪詢外部停止信號等。

這不是一項微不足道的任務,因為根據您的要求,它可能非常復雜。

計時器的問題在於,如果您想要一個好的計時器,您可能需要超越 C++/C 進入操作系統調用領域,這導致您最終得到特定於操作系統的解決方案或使用諸如 boost 之類的庫來包裝它。

我主要在 Windows 中編程,所以我的建議來自該領域:

在 Windows 中,您當然可以使用一些建議的timer(NULL) 然而,大多數情況下,當你在等待時,你不想讓 CPU 陷入循環。 使用 sleep 是一種方法,但我通常采用使用對象等待的方法。 對象發出信號或發生超時。 例如為了等待 10 秒:

res = WaitForSingleObject( someobjecthandle, 10000 );

如果返回值是超時,我知道我等了 10 秒,否則對象以某種方式發出信號,我沒有等 10 秒。 現在使用它,您可以創建一個有效的計時器。

另一種需要更多工作的方法是創建一個單獨的計時器線程(再次是 Windows),它會定期向您的消息循環發送消息。

第三種方法是創建一個作為實際計時器的線程,你用一個參數啟動線程,這次線程休眠(我知道你不想使用它,但你可以在線程內使用另一個 MsgWaitForMultipleObjects 函數來做出反應如果您想提前終止計時器)並在線程的句柄上執行 WaitForSingleObject ,當它發出信號時間已到(或超時)時。

有更多方法可以做到這一點,但這些只是一些起點。

許多這些答案包括所謂的“忙等待”。 在 99% 的情況下,在 while() 循環中一遍又一遍地檢查時間是個壞主意。

我想你可能想退后一步,以不同的方式解決這個問題。

聽起來您希望程序在給定的條件下關閉某些功能。

所以你有幾個選擇。 您可以每隔一段時間“喚醒”您的后台程序並檢查是否滿足條件(使用 sleep/usleep,這是所有操作系統上所有語言的標准功能)。

或者您可以無限期地將進程后台運行,直到發生某種類型的事件。 這可能最好通過信號或某種類型的等待函數在 C 中完成。

很難確切地說出您想要什么,因為很難說出您的待機/關閉條件是如何滿足以及它們是如何觸發的。

您可能希望您的電池監視器程序執行某種類型的 IPC,或者在需要待機時將某種類型的虛擬文件寫入已知目錄。 使用 IPC,您可以使用某種類型的 wait() 函數,該函數在將信號或 IPC 發送到后台進程時激活。 使用 file 方法,您可以 sleep(),並在每次喚醒時檢查該文件是否存在。

您也可以輕松地使用網絡/套接字來執行此操作。 偵聽環回接口 (127.0.0.1) 和預定義端口。 現在等待數據進入該套接字。 當電池監視器需要待機時,他會通過回送向您的新進程發送一條簡單的消息。 這將有效地使用 0 cpu。

可能還有其他方法,但我認為這應該給你一個大致的想法。

如果您所需要的只是讓您的程序休息的代碼片段,那么調用 sleep 就足夠了(如果您對第二個粒度沒問題)。

如果您需要使用單個線程運行多個計時器,那么維護一個包含活動計時器的哈希表是一個非常好的方法。 您使用到期時間來形成散列鍵。 每次計時器滴答時,您都會在哈希表中搜索已過期的計時器。

你總是可以玩弄線程。 一個主線程可以調度要在特定時間間隔執行的任務/作業。 但是接下來我們進入了調度領域,這是操作系統所做的事情。 因此,正如 GMan 所說,您突然進入了開發自己的操作系統或模仿部分操作系統功能的領域。

 void SimpleTimer(int timeinterval) { int starttime, currenttime, difference; starttime = time(null); do { currenttime = time(null); difference = currenttime - starttime; } while (difference < timeinterval); }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM