關(guān)于短延遲 sleep usleep nanosleep select
udelay(unsigned long usecs);
mdelay(unsigned long msecs); 前者用軟件循環(huán)指定的微妙數(shù),,后者調(diào)用前者達到延遲毫秒級,。udelay 函數(shù)只能用于獲取較短的時間延遲,因為loops_per_second值的精度只有8位,,所以,,當(dāng)計算更長的延遲時會積累出相當(dāng)大的誤差。盡管最大能允許的延遲將近1秒(因為更長的延遲就要溢出),,推薦的 udelay 函數(shù)的參數(shù)的最大值是取1000微秒(1毫秒),。延遲大于 11 毫秒時可以使用函數(shù) mdelay。
要特別注意的是 udelay 是個忙等待函數(shù)(所以 mdelay 也是),,在延遲的時間段內(nèi)無法運行其他的任務(wù),,因此要十分小心,尤其是 mdelay,,除非別無他法,,要盡量避免使用。 mdelay 在 Linux 2.0 中并不存在,,頭文件 sysdep.h 彌補了這一缺陷,。 關(guān)于 usleep sleep 主要的差距在精確程度上,不過網(wǎng)友有關(guān)于這個方面的精辟論斷:
同樣我覺得select也是比較好的定時機制,,不過大家可以看igmp-proxy的源代碼,。主函數(shù)里面用setitimer和select同時定時是一個相當(dāng)好的想法。 #################################################################
再論精確延時(usleep,nanosleep,select) /*
make: gcc -o test_sleep test_sleep.c */ /* #include "comm_main.h" */ #include <stdio.h>; #include <stdlib.h>; #include <time.h>; #include <sys/time.h>; #include <errno.h>; #include <string.h>; #include <unistd.h>; #include <sys/types.h>; #define PRINT_USEAGE { \
fprintf(stderr,"\n Usage: %s usec ",argv[0]); \ fprintf(stderr,"\n\n");\ } int
main (int argc, char **argv) { unsigned int nTimeTestSec = 0; /* sec */ unsigned int nTimeTest = 0; /* usec */ struct timeval tvBegin; struct timeval tvNow; int ret = 0; unsigned int nDelay = 0; /* usec */ fd_set rfds; struct timeval tv; int fd = 1; int i = 0; struct timespec req; unsigned int delay[20] = { 500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0 }; int nReduce = 0; /* 誤差 */ #if 0
if (argc < 2) { PRINT_USEAGE; exit (1); } nDelay = atoi (argv[1]); #endif fprintf (stderr, "%18s%12s%12s%12s\n", "function", "time(usec)", "realTime",
"reduce"); fprintf (stderr, "-------------------------------------------------------------------\n"); for (i = 0; i < 20; i++)
{ if (delay[i] <= 0) break; nDelay = delay[i]; /* test usleep */
gettimeofday (&tvBegin, NULL); ret = usleep (nDelay); if (-1 == ret) { fprintf (stderr, " usleep error . errno=%d [%s]\n", errno, strerror (errno)); } gettimeofday (&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t usleep %8u %8u %8d\n", nDelay, nTimeTest,nReduce); /* test nanosleep */ gettimeofday (&tvBegin, NULL); req.tv_sec = nDelay / 1000000; req.tv_nsec = (nDelay % 1000000) * 1000; ret = nanosleep (&req, NULL); if (-1 == ret) { fprintf (stderr, "\t nanosleep %8u not support\n", nDelay); } else { gettimeofday (&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t nanosleep %8u %8u %8d\n", nDelay, nTimeTest, nReduce); } /* test select */
gettimeofday (&tvBegin, NULL); FD_ZERO (&rfds); FD_SET (fd, &rfds); tv.tv_sec = 0; tv.tv_usec = nDelay; ret = select (0, NULL, NULL, NULL, &tv); if (-1 == ret) { fprintf (stderr, " select error . errno=%d [%s]\n", errno, strerror (errno)); } gettimeofday (&tvNow, NULL); nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec; nReduce = nTimeTest - nDelay; fprintf (stderr, "\t select %8u %8u %8d\n", nDelay, nTimeTest, nReduce); }
return 0;
} ---------------------------------------------------------------------------------------------------------------------------------------------------
測試
IBM AIX 3.4 單CPU sleep 可以在多線程中使用,,只阻塞本線程,,不影響所屬進程中的其它線程 不支持 nanosleep 支持 usleep 和 select 以下采用 gettimeofday 對 usleep 和 select 的實際精確情況進行測試分析 function time(usec) realTime reduce ------------------------------------------------------------------- usleep 500000 500026 26 nanosleep 500000 not support select 500000 500026 26 usleep 100000 100021 21 nanosleep 100000 not support select 100000 100025 25 usleep 50000 50021 21 nanosleep 50000 not support select 50000 50107 107 本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/jifengszf/archive/2009/04/14/4073340.aspx |
|