linux下多定時器的實現(經典)
一、已有的定時器介面
時空管理是計算機系統的主要任務。在時間管理中,我們經常利用定時器處理事情:比如tcp協議中利用定時器管理包超時,視訊顯示中利用定時器來定時顯示視訊幀,web服務中利用定時器來管理使用者的超時。windows系統提供了SetTimer和timeSetEvent等定時器介面,linux中則提供了setitimer等介面。這些函式的介面很類似,大體上都是使用者提供回撥函式和超時時間向OS註冊一個定時器事件,OS在超時時間到了的時候,呼叫使用者提供的回撥函式來完成使用者想要做的事情。windows下的介面支援單程式中擁有多個定時器,而linux則只允許單程式擁有一個定時器,因此在linux下的單程式中要使用多個定時器,則需要自己維護管理,這是本文寫作的出發點。另外,OS提供的定時器管理演算法在大規模定時器的管理方面可能還不盡人意,這時候就需要使用者去優化管理演算法了,本文在這方面提供了一點素材。
二、一個最簡單的多定時器的實現(linux版)
1、實現細節
這個實現允許使用者使用多個自定義的定時器,每個自定義的定時器將週期地被觸發直到其被刪除。實現的主要思路是:
i)首先在初始化多定時器(init_mul_timer)時利用setitimer註冊一個基本的時間單位(如1s)的定時事件;
ii)使用者需要set_a_timer註冊自定義定時器時,在timer_manage管理結構中記錄這個定時器的回撥函式和定時週期等引數;
iii)當基本的時間單位到期後(如SIGALRM訊號到達時),遍歷整個timer_manage,如果有自定義定時器的超時時間到了,就執行相應的回撥函式,並將自定義定時器的超時時間置為最初值;否則將自定義定時器的超時時間相應地減一個基本的時間單位;
iv)使用者通過del_a_timer來刪除某個定時器,通 過destroy_mul_timer來刪除整個多定時器。
2、程式碼
i) mul_timer.h
|
ii)mul_timer.c
|
3、缺陷
i)新建定時器、遍歷定時器和刪除定時器(查詢哪個定時器超時)時時間複雜度都為O(n)(n是定時器的個數);
ii)適用環境是單執行緒環境,如要用於多執行緒,需新增同步操作。
iii)程式中有些小bug,如對新建超時時間為0的定時器沒有妥善的處理。
三、多定時器的改進版
1、思路
改進定時器的實現,即是改善二種所指出的幾個缺陷,如下是一個改進版,主要是將遍歷超時時間的時間複雜度降為了O(1).
改善思路:各定時器以一個連結串列的形式組織起來,除連結串列頭定時器的超時時間是用絕對時間紀錄的外,其它定時器的超時時間均用相對時間(即超時時間-前一個定時器的超時時間)紀錄.
注意,各定時器都是一次性的,當定時器的超時被處理後,定時器將被自動刪除.另外如果將定時器的結點改為雙向結構,可以將刪除定時器的時間複雜度降為O(1).
2、資料結構
每個定時器都有一個唯一的ID,這個ID是如下的結構體:
|
ptr紀錄的是定時器結點的地址,entry_id則是一個自多定時器初始化後自增的id.ptr和entry_id一起組成定時器結點的key,一方面使得新建定時器時生成key的過程大為簡化,另一方面使得刪除定時器的時間複雜度降為O(1)(前提是定時器結點採用雙向結構)。
定時器結點的資料結構如下:
|
其中的is_use是用來防止這樣一種情況:使用者在回撥函式中呼叫kill_timer來刪除定時器,這個時候kill_timer和遍歷定時器中都有刪除結點的操作,有可能將整個連結串列搞混亂。所以在呼叫使用者的回撥函式前先將is_use置1,在kill_timer中需檢查is_use,只有在 is_use為0的情況下,才執行清理定時器結點的操作。
3、程式碼(windows版)
i)mul_timer.h
|
ii)mul_timer.c
|
3、缺陷
i)新建定時器的時間複雜度為O(n),刪除定時器的時間複雜度也為O(n)(簡單地將定時器結點改為雙向結構,可將複雜度降為O(1));
ii)不能用於多執行緒環境
四 、多定時器的工業級實現
1、time wheelz演算法
以前的BSD核心以及現在的linux核心的實現與三中所用演算法相似(未實證,只是據說),據說現在的BSD核心已採用了較好的time wheelz演算法。
time wheez演算法的優點:
i)將新建定時器的時間複雜度降近似為O(1)。它根據定時器的超時值,將新定時器雜湊到hash桶中;
ii)遍歷檢查定時器的時間複雜度也近似為O(桶大小),如果雜湊均勻。
iii)刪除定時器的時間複雜度近似為O(1),通過hash演算法或臨時儲存(空間換時間的演算法)。
2、time wheelz的實現
請參考文末給出的兩個論文,慚愧得很,文章我也只是稍微瞄了下,以後有用得著的時候再深究吧。
轉自 http://blog.csdn.net/zhangxinrun/article/details/5914191
相關文章
- 關於linux下定時器,多定時器Linux定時器
- Laravel + Workerman 實現多程式定時器任務Laravel定時器
- 實現累加的經典sql方法SQL
- 定時 MYSQL 動作-LINUX下用CRON實現定時執行指令碼(轉)MySqlLinux指令碼
- 【JavaScript定時器小案例】常見的幾種定時器實現的案例JavaScript定時器
- Go定時器的三種實現方式Go定時器
- 經典手眼標定演算法之Tsai-Lenz的OpenCV實現演算法AIOpenCV
- Python實現定時任務的多種方式Python
- spring quartz如何實現多工定時Springquartz
- linux下使用TCP存活(keepalive)定時器LinuxTCP定時器
- C++定時器CTimer的實現C++定時器
- Spring定時器的兩種實現方式Spring定時器
- 現實生活:定時器&孔子的一生定時器
- linux下兩臺伺服器檔案實時同步方案實現Linux伺服器
- linux實現一個定時任務Linux
- Linux中如何實現定時任務Linux
- Linux核心定時器Linux定時器
- Linux 定時器alarm()Linux定時器
- Linux下的定時任務crontab設定Linux
- Java可自定義中斷定時器的實現Java定時器
- 使用監聽器實現JavaWeb的定時執行JavaWeb
- 23個經典設計模式的Swift實現設計模式Swift
- Golang 定時器底層實現深度剖析Golang定時器
- Laravel 結合 Redis 實現 PHP 定時器LaravelRedisPHP定時器
- .NET中如何實現高精度定時器定時器
- c++控制檯程式實現定時器C++定時器
- 【STM32F4】利用定時器實現最基本的定時功能(HAL)定時器
- JavaScript實現經典排序演算法JavaScript排序演算法
- 經典排序演算法PHP實現排序演算法PHP
- js實現0ms延時定時器的幾種方式JS定時器
- 實現 .Net 7 下的資料庫定時檢查資料庫
- ScheduledThreadPoolExecutor實現定時器和延時載入功能thread定時器
- 定時任務的實現
- 關於在linux下磁碟定額的實現(轉)Linux
- ios 多執行緒定時器iOS執行緒定時器
- Linux的10個經典彩蛋Linux
- javascript 日期時間函式(經典+完善+實用)JavaScript函式
- java springboot 實現定時器任務JavaSpring Boot定時器