Unix C 延時函式小結

2021-08-23 15:42:40 字數 3828 閱讀 4097

在多執行緒的應用中要用到延時函式,開始時我只用到 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的延遲時間則使以具體時間大小來很亮的。這兩個函式有著非常重要的作用,就是...