在多執行緒的應用中要用到延時函式,開始時我只用到 sleep 這個秒級函式,但在 solaris 上跑時,程式執行到sleep時,卻顯示 「alarm clock」 這句話後就中止了。據說是產生了 alarm 這個訊號,而系統預設訊號處理就是中止程式,所以要在程式中把這個設定為忽略:
signal(sigalrm, sig_ign);
unix 上的延時函式有好幾種:
[quote]
一、 基礎知識
1、時間型別。linux下常用的時間型別有4個:time_t,struct timeval,struct timespec,struct tm。
(1)time_t是乙個長整型,一般用來表示用2023年以來的秒數。
(2)struct timeval有兩個成員,乙個是秒,乙個是微妙。
struct timeval ;
(3)struct timespec有兩個成員,乙個是秒,乙個是納秒。
struct timespec;
(4)struct tm是直觀意義上的時間表示方法:
struct tm ;
2、 時間操作
(1) 時間格式間的轉換函式
主要是 time_t、struct tm、時間的字串格式之間的轉換。看下面的函式引數型別以及返回值型別:
char *asctime(const struct tm *tm);
char *ctime(const time_t *timep);
struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
time_t mktime(struct tm *tm);
gmtime和localtime的引數以及返回值型別相同,區別是前者返回的格林威治標準時間,後者是當地時間。
(2) 獲取時間函式
兩個函式,獲取的時間型別看原型就知道了:
time_t time(time_t *t);
int gettimeofday(struct timeval *tv, struct timezone *tz);
前者獲取time_t型別,後者獲取struct timeval型別,因為型別的緣故,前者只能精確到秒,後者可以精確到微秒。
二、 延遲函式
主要的延遲函式有:sleep(),usleep(),nanosleep(),select(),pselect().
unsigned int sleep(unsigned int seconds);
void usleep(unsigned long usec);
int nanosleep(const struct timespec *req, struct timespec *rem);
int select(int n, fd_set *readfds,fd_set *writefds,fd_set *exceptfds,
struct timeval *timeout);
int pselect(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,
const struct timespec *timeout, const sigset_t *sigmask);
alarm函式是訊號方式的延遲,這種方式不直觀,這裡不說了。
僅通過函式原型中時間引數型別,可以猜測sleep可以精確到秒級,usleep/select可以精確到微妙級,nanosleep和pselect可以精確到納秒級。
而 實際實現中,linux上的nanosleep和alarm相同,都是基於核心時鐘機制實現,受linux核心時鐘實現的影響,並不能達到納秒級的精度, man nanosleep也可以看到這個說明,man裡給出的精度是:linux/i386上是10 ms ,linux/alpha上是1ms。
這裡有一篇文章 測試了不同延遲函式之間的精確度。文章給出的結論是linux上精度最高的是select,10ms級別。我在本機器測試select和pselect相 當,都達到了1ms級的精度,精度高於文章中給出的10ms,sleep在秒級以上和usleep/nanosleep相當。下面貼下我機器上1ms時候 的測試結果,其他不貼了:
sleep 1000 0 -1000
usleep 1000 2974 1974
nanosleep 1000 2990 1990
select 1000 991 -9
pselect 1000 990 -10
gettimeofday 1000 1000 0
而使用gettimeofday迴圈不停檢測時間,可精確微秒級,不過不適宜用來做定時器模組。
因此後面的定時期模組將選擇select為延遲函式。
[/quote]
我在用 usleep 時卻發現有部分執行緒完全在等待中,沒有醒過來, 最後換用了 nanosleep
正常回了。注意,要呼叫 nanosleep, 編譯時要帶 -lposix4
nanosleep 的例子(來自
#include
#include
#include
#include
#include
#define count 1000
#define million 1000000l
int main(void)
for (i = 0; i < count; i++)
}if (gettimeofday(&tend, null) == -1)
tdif = million * (tend.tv_sec - tstart.tv_sec) + (tend.tv_usec - tstart.tv_usec);
printf("nanosleep() time is %ld us\n", tdif/count);
return 0;
}hz 250hz
時鐘中斷的時間間隔: 4 ms (1000ms/250)
----------------------------------------
nanosleep() time is 4019 us (4.019 ms)
說明nanosleep的睡眠定時器依賴於時鐘中斷
hz 1000hz
時鐘中斷的時間間隔: 1 ms
----------------------------------------
nanosleep() time is 12 us
注: 最小睡眠時間為1 us
Linux延時函式
每乙個平台不太一樣,最好自己定義一套跨平台的巨集進行控制。dos sleep 1 停留1秒 delay 100 停留100毫秒 windows sleep 100 停留100毫秒 linux sleep 1 停留1秒 usleep 1000 停留1毫秒 每乙個平台不太一樣,最好自己定義一套跨平台的巨...
Linux 核心延時函式
linux核心提供3個函式分別進行納秒,微妙和毫秒延時 void ndelay unsigned long nsecs void udelay unsigned long usecs void mdelay unsigned long msecs 這3個函式的延時原理是忙等待,也就是說在延時的過程中...
ucos 任務延時函式
在ucos裡,系統也提供了這樣的延時函式,乙個是大眾版本ostimedly 乙個是精緻版本的ostimedlyhmsm 隨你怎麼選擇 這兩者的區別就是,ostimedly的延時時間是以節拍數來衡量的額,ostimedlyhmsm的延遲時間則使以具體時間大小來很亮的。這兩個函式有著非常重要的作用,就是...