1. 程式人生 > >Linux高精確的時序(sleep, usleep,nanosleep)

Linux高精確的時序(sleep, usleep,nanosleep)

 int nanosleep(const struct timespec *req, struct timespec *rem);

 struct timespec
              {
                      time_t  tv_sec;         /* seconds */
                      long    tv_nsec;        /* nanoseconds */
              };

這個函式功能是暫停某個程序直到你規定的時間後恢復,引數req就是你要暫停的時間,其中req->tv_sec是以秒為單位,而tv_nsec以毫微秒為單位(10的-9次方秒)。由於呼叫nanosleep是是程序進入TASK_INTERRUPTIBLE,這種狀態是會相應訊號而進入TASK_RUNNING狀態的,這就意味著有可能會沒有等到你規定的時間就因為其它訊號而喚醒,此時函式返回-1,切還剩餘的時間會被記錄在rem中。

看到這裡剛剛看到他的實現是:將其狀態設定成TASK_INTERRUPTIBLE,脫離就緒佇列,然後進行一次程序排程再由核心在規定的時間後傳送訊號來喚醒這個程序。

在我剛開始學習程式設計時候,那時候我也曾試圖使上下2條指令相隔一定時間來執行,那時我的做法是在這2條指令之間加上了一個400次的迴圈。這也算一種實現方式,我管它叫作延遲,但沒有利用程序休眠來實現的好。但有一種特殊情況,使用休眠就無法實現了。

我們知道這裡肯定脫離不了時鐘中斷,沒有時鐘中斷的計時我們是無法實現這一功能的。那麼假設時鐘種中斷是10毫秒一次(這種CPU還是有的),那麼我們可以看到在函式呼叫的時候我們可以以毫微秒來暫停,如果我tv_sec = 0, tv_nsec = 2,那麼時鐘中斷一定是在10微秒後來喚醒這個程序的,如果非實時性任務差個8微秒估計沒什麼大不了,不幸的是LINUX支援實時性任務SCHED_FIFO和SCHED_RR.(我們以前談到過)。

這時8微秒的差距就是不能容忍了,這是就不能靠休眠和時鐘中斷來實現了,這是linux採用就是延遲辦法,執行一個迴圈來達到暫停的目的。

這2種實現的差別就是休眠實現的話,程序會進入休眠狀態,而延遲實現的話,CPU是在執行迴圈不會進入休眠態。所以可以說雖然名為nanosleep,但它不一定會使程序進入sleep狀態,當然不進入sleep 態的條件太苛刻(沒多少人會寫實時任務,且還是暫停要小於CPU時鐘頻率,加上現在CPU的頻率是如此之高,這種情況一般發生在要求外設中斷不小於某個特定值,而且應該是採用比較老的CPU或者嵌入式中)。