在實際的C程序中,一個模塊執行多個操作是很常見的事情。如果多個操作同時進行,會出現程序效率低下、計算機CPU占用率過高等情況,這時就需要對所有操作的執行順序作一個合理的安排,這就涉及到定時器的使用。
本文對C程序中的定時器的類型、設置和清除方法等作了詳細的介紹,為相關開發工作的開展提供了參考。
一、定時器的定義及分類
我們所熟悉的定時器是一個多任務定時提醒的軟件,安裝於電腦或手機上。舉個例子,我們經常用的鬧鐘其實就是定時器,它會在我們設定的時間運行某種程序,在其它時間則處於休眠狀態。
那麼什麼是C程序中的定時器呢?C程序中的定時器是程序員編寫的用於定時執行某種操作的程序,是相關C代碼的集合。這個定時器是“幕後的英雄”,我們能夠看到的是軟件所體現出來的某項功能,而看不見的是定時器所起的作用。
根據所起的作用的不同,C程序中的定時器分為如下兩類:
第一類,在多個操作中設定不同操作執行順序的定時器。在一個很大的軟件模塊中,同時進行多個操作會降低程序的執行效率,合理地使用定時器能夠讓某些操作避開程序執行的“高峰期”,達到舒緩程序執行壓力的作用。這時的定時器所起的作用和在上下班時間十字路口的紅綠燈的作用類似。
第二類,用於限制某種操作的執行時間,若在規定時間內沒有執行該操作則作超時處理的定時器。這類定時器多用於需要和其它模塊進行通信的模塊中。如果一個模塊向其它模塊發了一個很重要的消息,需要等到其它模塊答復後才能進行下一步的操作,那麼定時器就在這個時候派上用場了。可以在定時器中設定本模塊所能“容忍”的其它模塊最遲應答的時間,如果超過了這個時間,則認為對方無應答,直接進行後續操作。
在C程序中,合理利用定時器,可提高程序的執行效率,同時可讓程序體現出邏輯層次感和嚴密性。
二、定時器的數據結構
為了完成功能,一個典型的定時器的數據結構如下:
// 先重定義基本數據類型 typedef unsigned char UINT8; typedef unsigned short int UINT16; typedef unsigned int UINT32; // 定時器的數據結構 typedef struct { …… …… UINT8 iUseFlag; // 該定時器是否正在使用 UINT8 iArrivedFlag; // 使用該定時器的時間是否已到 UINT8 iTimerType; // 該定時器的類型 UINT16 iModuleNo; // 使用該定時器的模塊號/進程號等信息 UINT32 iSetTime; // 設定該定時器的啟動時間, 即相對此刻, 該定時器在多長時間之後啟動 UINT8 iTimerNo; // 該定時器的編號 UINT8 iQue; // 該定時器的存放隊列 UINT16 iQuePrev; // 該定時器的存放位置的前一個結點 UINT16 iQueNext; // 該定時器的存放位置的後一個結點 …… …… } TimerStruc_T;
一個定時器結構體所包含的字段根據不同軟件產品和項目組的要求而略有區別,但如上面結構體中羅列出來的字段都是需要的。字段的含義見對應字段後面的注釋。
三、如何設置和清除定時器
在實際的軟件開發項目中,一般將設置定時器的流程封裝為函數。在需要設置定時器的時候,只需要調用該函數即可。
設置定時器的流程如圖1所示。
圖1 設置定時器的流程
有關此流程的說明如下:
(1) 在設置定時器之前,先要判斷該定時器是否正在使用。如果在使用中,那麼要先清除定時器以釋放資源。這是為了防止一個定時器有多種用途的情況。
(2) 在獲取定時器存放資源之前,要對初始化及信息入隊操作進行加鎖處理。為了防止同樣的資源被多個定時器獲得。
清除定時器的操作同樣會被封裝為函數。在需要清除定時器的時候,只需要調用該函數即可。
清除定時器的流程如圖2所示。
圖2 清除定時器的流程
有關此流程的說明如下:
(1) 在清除定時器之前,先要判斷該定時器是否正在使用及清除時間是否達到。如果兩者中有一個不滿足,則不用清除定時器。
(2) 在清除定時器相關信息之前,為了保持操作的唯一性,同樣要進行加鎖處理。
四、總結
隨著程序功能的日益完善和豐富,不同操作執行順序越發顯得重要,這就為定時器提供了施展才能的“舞台”。
本文以作者的實際項目開發工作為背景,對C程序中的定時器的類型、設置和清除方法等作了詳細的描述,為相關模塊的設計和程序的編寫提供了有益的參考。