linux使用select實現(xiàn)精確定時器詳解
更新時間:2013年11月14日 11:11:11 作者:
本文講述如何使用select實現(xiàn)超級時鐘。使用select函數(shù),我們能實現(xiàn)微妙級別精度的定時器。同時,select函數(shù)也是我們在編寫非阻塞程序時經(jīng)常用到的一個函數(shù)
在編寫程序時,我們經(jīng)常會用到定時器。首先看看select函數(shù)原型如下:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
參數(shù)說明:
slect的第一個參數(shù)nfds為fdset集合中最大描述符值加1,fdset是一個位數(shù)組,其大小限制為__FD_SETSIZE(1024),位數(shù)組的每一位代表其對應(yīng)的描述符是否需要被檢查。
select的第二三四個參數(shù)表示需要關(guān)注讀、寫、錯誤事件的文件描述符位數(shù)組,這些參數(shù)既是輸入?yún)?shù)也是輸出參數(shù),可能會被內(nèi)核修改用于標(biāo)示哪些描述符上發(fā)生了關(guān)注的事件。所以每次調(diào)用select前都需重新初始化fdset。
timeout參數(shù)為超時時間,該結(jié)構(gòu)會被內(nèi)核修改,其值為超時剩余的時間。
利用select實現(xiàn)定時器,需要利用其timeout參數(shù),注意到:
1)select函數(shù)使用了一個結(jié)構(gòu)體timeval作為其參數(shù)。
2)select函數(shù)會更新timeval的值,timeval保持的值為剩余時間。
如果我們指定了參數(shù)timeval的值,而將其他參數(shù)都置為0或者NULL,那么在時間耗盡后,select函數(shù)便返回,基于這一點,我們可以利用select實現(xiàn)精確定時。
timeval的結(jié)構(gòu)如下:
struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}
我們可以看出其精確到microseconds也即微妙。
一、秒級定時器
void seconds_sleep(unsigned seconds){
struct timeval tv;
tv.tv_sec=seconds;
tv.tv_usec=0;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
二、毫秒級別定時器
void milliseconds_sleep(unsigned long mSec){
struct timeval tv;
tv.tv_sec=mSec/1000;
tv.tv_usec=(mSec%1000)*1000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
三、微妙級別定時器
void microseconds_sleep(unsigned long uSec){
struct timeval tv;
tv.tv_sec=uSec/1000000;
tv.tv_usec=uSec%1000000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
現(xiàn)在我們來編寫幾行代碼看看定時效果吧。
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
int i;
for(i=0;i<5;++i){
printf("%d\n",i);
//seconds_sleep(1);
//milliseconds_sleep(1500);
microseconds_sleep(1900000);
}
}
注:timeval結(jié)構(gòu)體中雖然指定了一個微妙級別的分辨率,但內(nèi)核支持的分別率往往沒有這么高,很多unix內(nèi)核將超時值向上舍入成10ms的倍數(shù)。此外,加上內(nèi)核調(diào)度延時現(xiàn)象,即定時器時間到后,內(nèi)核還需要花一定時間調(diào)度相應(yīng)進程的運行。因此,定時器的精度,最終還是由內(nèi)核支持的分別率決定。
分類: Linux
復(fù)制代碼 代碼如下:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
參數(shù)說明:
slect的第一個參數(shù)nfds為fdset集合中最大描述符值加1,fdset是一個位數(shù)組,其大小限制為__FD_SETSIZE(1024),位數(shù)組的每一位代表其對應(yīng)的描述符是否需要被檢查。
select的第二三四個參數(shù)表示需要關(guān)注讀、寫、錯誤事件的文件描述符位數(shù)組,這些參數(shù)既是輸入?yún)?shù)也是輸出參數(shù),可能會被內(nèi)核修改用于標(biāo)示哪些描述符上發(fā)生了關(guān)注的事件。所以每次調(diào)用select前都需重新初始化fdset。
timeout參數(shù)為超時時間,該結(jié)構(gòu)會被內(nèi)核修改,其值為超時剩余的時間。
利用select實現(xiàn)定時器,需要利用其timeout參數(shù),注意到:
1)select函數(shù)使用了一個結(jié)構(gòu)體timeval作為其參數(shù)。
2)select函數(shù)會更新timeval的值,timeval保持的值為剩余時間。
如果我們指定了參數(shù)timeval的值,而將其他參數(shù)都置為0或者NULL,那么在時間耗盡后,select函數(shù)便返回,基于這一點,我們可以利用select實現(xiàn)精確定時。
timeval的結(jié)構(gòu)如下:
復(fù)制代碼 代碼如下:
struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}
我們可以看出其精確到microseconds也即微妙。
一、秒級定時器
復(fù)制代碼 代碼如下:
void seconds_sleep(unsigned seconds){
struct timeval tv;
tv.tv_sec=seconds;
tv.tv_usec=0;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
二、毫秒級別定時器
復(fù)制代碼 代碼如下:
void milliseconds_sleep(unsigned long mSec){
struct timeval tv;
tv.tv_sec=mSec/1000;
tv.tv_usec=(mSec%1000)*1000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
三、微妙級別定時器
復(fù)制代碼 代碼如下:
void microseconds_sleep(unsigned long uSec){
struct timeval tv;
tv.tv_sec=uSec/1000000;
tv.tv_usec=uSec%1000000;
int err;
do{
err=select(0,NULL,NULL,NULL,&tv);
}while(err<0 && errno==EINTR);
}
現(xiàn)在我們來編寫幾行代碼看看定時效果吧。
復(fù)制代碼 代碼如下:
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
int i;
for(i=0;i<5;++i){
printf("%d\n",i);
//seconds_sleep(1);
//milliseconds_sleep(1500);
microseconds_sleep(1900000);
}
}
注:timeval結(jié)構(gòu)體中雖然指定了一個微妙級別的分辨率,但內(nèi)核支持的分別率往往沒有這么高,很多unix內(nèi)核將超時值向上舍入成10ms的倍數(shù)。此外,加上內(nèi)核調(diào)度延時現(xiàn)象,即定時器時間到后,內(nèi)核還需要花一定時間調(diào)度相應(yīng)進程的運行。因此,定時器的精度,最終還是由內(nèi)核支持的分別率決定。
分類: Linux
相關(guān)文章
shell腳本實現(xiàn)拷貝大文件顯示百分比的代碼分享
這篇文章主要介紹了shell腳本實現(xiàn)拷貝大文件顯示百分比的代碼分享,需要的朋友可以參考下2014-08-08linux?shell字符串操作詳解(長度、讀取、替換、截取、連接、對比、刪除及位置)
字符串是shell編程中最常用最有用的數(shù)據(jù)類型,這篇文章主要給大家介紹了關(guān)于linux?shell字符串操作(長度、讀取、替換、截取、連接、對比、刪除及位置)的相關(guān)資料,需要的朋友可以參考下2024-03-03淺談:linux cron 計劃任務(wù)常用符號小結(jié)
本文給大家介紹linux cron計劃任務(wù)常用符號小結(jié),感興趣的朋友跟著小編一起學(xué)習(xí)吧2015-10-10Linux的打包壓縮與解壓縮---tar、xz、zip、unzip命令詳解
Linux 下一堆各式各樣的壓縮文件名:.gz、.tar.gz、tgz、bz2、.Z、.tar 等眾多的壓縮文件名,本文重點介紹Linux的打包壓縮與解壓縮---tar、xz、zip、unzip命令,感興趣的朋友一起看看吧2024-02-02linux shell命令快捷獲得系統(tǒng)幫助(一)[man-pages定義規(guī)范]
linux命令幫助,一般有2種,命令自身代碼里面帶有使用幫助說明,這種一般很精簡,太長了,程序自身的大小以及日常維護不方便。還有一種,就是帶有幫助文件,類似windows的chm格式文件。下面我說下這2種怎么樣查閱2015-10-10