1. 程式人生 > >linux獲取高精度時間的方法

linux獲取高精度時間的方法

編寫linux下應用程式的時候,有時候會用到高精度相對時間的概念,比如間隔100ms。那麼應該使用哪個時間函式更準確呢?

1、time
該函式返回的是自1970年以來的秒數,顯然精度不夠,不能使用
2、gettimeofday
該函式返回的是自1970年以來的秒數和微秒數,精度顯然是夠了。我想有很多程式設計師也是用的這個函式來計算相對時間的,如果說系統時間因為ntp等原因發生時間跳變,那麼用這個函式來計算相對時間是不是就會出問題了。所以說這個函式也不能使用
3、clock_gettime
該函式提供了4種類型CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_PROCESS_CPUTIMEID、CLOCK_THREAD_CPUTIME_ID。從字面意思可以判斷出來,CLOCK_MONOTONIC提供了單調遞增的時間戳,該函式返回值為自系統啟動後秒數和納秒數,但是該函式沒有考慮ntp的情況,所以並不是絕對意義上的單調遞增(見二)。
CLOCK_REALTIME is affected by settime()/settimeofday() calls and can also be frequency corrected by NTP via adjtimex().
CLOCK_MONOTONIC is not affected by settime()/settimeofday(), but is frequency adjusted by NTP via adjtimex().With Linux,NTP normally uses settimeofday() for large corrections (over half a second). The adjtimex() inteface allows for small clock frequency changes (slewing). This can be done in a few different ways, see the man page for adjtimex.
CLOCK_MONOTONIC_RAW that will not be modified at all, and will have a linear correlation with the hardware counters.
4、syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &monotonic_time)
該函式提供了真正意義上的單調遞增時間(見三)

glibc 中clock_gettime(CLOCK_MONOTONIC)的原理

檢視glibc的程式碼可以看到這個數值是由核心計算的。

__vdso_clock_gettime-------->do_monotonic
這個函式的實現如下:

點選(此處)摺疊或開啟
notrace static noinline int do_monotonic(struct timespec *ts)
{
unsigned long seq, ns, secs;
do {
seq = read_seqbegin(&gtod->lock);
secs = gtod->wall_time_sec;
ns = gtod->wall_time_nsec + vgetns();
secs += gtod->wall_to_monotonic.tv_sec;
ns += gtod->wall_to_monotonic.tv_nsec;
} while (unlikely(read_seqretry(&gtod->lock, seq)));

    /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
     * are all guaranteed to be nonnegative.
     */
    while (ns >= NSEC_PER_SEC) {
            ns -= NSEC_PER_SEC;
            ++secs;
    } 
    ts->tv_sec = secs;
    ts->tv_nsec = ns; 

    return 0;

}
這個程式碼讀取牆上時間,然後加上相對於單調時間的便宜,從而得到單調時間,但是這裡並沒有考慮ntp通過adjtimex()調整小的時間偏差的情況,所以這個仍然不是絕對的單調遞增。

核心clock_gettime系統呼叫

在kernel/posix-timers.c中核心實現了clock_gettime的系統呼叫,包括CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_MONOTONIC_RAW、CLOCK_REALTIME_COARSE、CLOCK_MONOTONIC_COARSE、CLOCK_BOOTTIME等型別,這裡我們看一下CLOCK_MONOTONIC_RAW的實現

點選(此處)摺疊或開啟
struct k_clock clock_monotonic_raw = {
.clock_getres = hrtimer_get_res,
.clock_get = posix_get_monotonic_raw,
};

posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);

/*
* Get monotonic-raw time for posix timers
*/
static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp)
{
getrawmonotonic(tp);
return 0;
}

/**
* getrawmonotonic - Returns the raw monotonic time in a timespec
* @ts: pointer to the timespec to be set
*
* Returns the raw monotonic time (completely un-modified by ntp)
*/
void getrawmonotonic(struct timespec *ts)
{
unsigned long seq;
s64 nsecs;

    do {
            seq = read_seqbegin(&xtime_lock);
            nsecs = timekeeping_get_ns_raw();
            *ts = raw_time;

    } while (read_seqretry(&xtime_lock, seq));

    timespec_add_ns(ts, nsecs);

}
EXPORT_SYMBOL(getrawmonotonic);

static inline s64 timekeeping_get_ns_raw(void)
{
cycle_t cycle_now, cycle_delta;
struct clocksource *clock;

    /* read clocksource: */
    clock = timekeeper.clock;
    cycle_now = clock->read(clock);

    /* calculate the delta since the last update_wall_time: */
    cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;

    /* return delta convert to nanoseconds using ntp adjusted mult. */
    return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);

}

四、關於wall time和monotonic time
wall time:xtime,取決於用於對xtime計時的clocksource,它的精度甚至可以達到納秒級別,核心大部分時間都是使用xtime來獲得當前時間資訊,xtime記錄的是自1970年當前時刻所經歷的納秒數。
monotonic time: 該時間自系統開機後就一直單調地增加(ntp adjtimex會影響其單調性),它不像xtime可以因使用者的調整時間而產生跳變,不過該時間不計算系統休眠的時間,也就是說,系統休眠時(total_sleep_time),monotoic時間不會遞增。
raw monotonic time: 該時間與monotonic時間類似,也是單調遞增的時間,唯一的不同是,raw monotonic time不會受到NTP時間調整的影響,它代表著系統獨立時鐘硬體對時間的統計。
boot time: 與monotonic時間相同,不過會累加上系統休眠的時間(total_sleep_time),它代表著系統上電後的總時間。
五、總結
在linux下獲取高精度單調遞增的時間,只能使用syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &monotonic_time)獲取!

相關推薦

linux獲取精度時間方法

編寫linux下應用程式的時候,有時候會用到高精度相對時間的概念,比如間隔100ms。那麼應該使用哪個時間函式更準確呢? 1、time 該函式返回的是自1970年以來的秒數,顯然精度不夠,不能使用 2、gettimeofday

linux精度時間

定時器 精度 處理 turn 通過 公司 cti include processor 今天在公司代碼中看到了使用select函數的超時功能作定時器的用法,便整理了如下幾個Linux下的微秒級別的定時器。在我的Ubutu10.10 雙核環境中,編譯通過。 [cpp] vi

linux下的精度時間函式

apue2nd書中 沒有對於linux平臺下時間函式的例子,僅僅是介紹了一下api,不太方便我們使用,這裡找了一些例子, #include <stdio.h>#include <time.h>#include <sys/timeb.h>in

windows 精度時間獲取

//不好意思,困了,懶得解釋了 //標頭檔案File:TimeTool.h #ifndef TIMETOOL_H_INCLUDED #define TIMETOOL_H_INCLUDED #include <windows.h> typedef struct P

linux中C語言獲取精度時鐘gettimeofday函式

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/time.h> 5 int time_substract(struct timev

linux獲取系統啟動時間

pre 現在 red str family nds stderr 表達方式 space 1、前言   時間對操作系統來說非常重要,從內核級到應用層,時間的表達方式及精度各部相同。linux內核裏面用一個名為jiffes的常量來計算時間戳。應用層有time、getdayti

Ubuntu上C++精度時間的測量

clock()函式的精確度是10毫秒(ms) times()函式的精確度是10毫秒(ms) gettimofday()函式的精確度是微秒(μs) clock_gettime()函式的計量單位為十億

c/c++ 精度時間測試

測量程式執行時間(ms級) 高精度時控函式QueryPerformanceFrequency(),QueryPerformanceCounter() 原理:QueryPerformanceCounter()這個函式返回高精確度效能計數器的值,它可以以微妙為單位計時.但是Qu

【vc】精度時間函式的使用

方法一: 函式定義如下: int UsSleep(int us);//返回實際的微秒延時時間 程式碼實現如下: 1 //引數一表示 需要等待的時間 微秒為單位 2 int UsSleep(int us) 3 { 4 //儲存計數的聯合 5 LARGE_INTE

【vc】精度時間函數的使用

amp color 定義 定時 表示 per 2個 target title 方法一: 函數定義如下: int UsSleep(int us);//返回實際的微秒延時時間 代碼實現如下: 1 //參數一表示 需要等待的時間 微秒為單位 2 int UsSleep(

Delphi精度計時方法

//取毫秒級時間精度(方法一):vart1,t2:int64;r1:int64;begint1:=GetTickCount;//獲取開始計數 WINDOWS APIsleep(1000);{do...}//執行要計時的程式碼t2:=GetTickCount;//獲取結束計數值

C++中獲得CPU精度時間戳( 納秒級 )

對關注效能的程式開發人員而言,一個好的計時部件既是益友,也是良師。計時器既可以作為程式元件幫助程式設計師精確的控制程式程序,又是一件有力的除錯武器,在有經驗的程式設計師手裡可以儘快的確定程式的效能瓶頸,或者對不同的演算法作出有說服力的效能比較。  在Windows平臺下,常用

LINUX獲取前一天日期的方法

獲取前一天日期的方法 .. 寫SHELL時,有時候很有用的..linux下 前一天的日期 date -d "1 day ago" +"%y%m%d" 前一個月的日期 date -d "1 month ago" +"%y%m%d" 類似的還有 date -d "-1 day

關於linux hrtimer精度定時器的使用註意事項

linux設備驅動 mar 定時函數 src int 這樣的 vpd 由於 高精 關於linux hrtimer高精度定時器的使用註意事項 需要註意:由於hrtimer本身沒有interval周期的概念,如果要實現hrtimer的周期調用,方法1) 超時函數,調用hrtim

Linux時間子系統之六:精度定時器(HRTIMER)的原理和實現

3.4 size 屬於 running return repr 而是 復雜度 ctu 上一篇文章,我介紹了傳統的低分辨率定時器的實現原理。而隨著內核的不斷演進,大牛們已經對這種低分辨率定時器的精度不再滿足,而且,硬件也在不斷地發展,系統中的定時器硬件的精度也越來越高,這也給

Linux kernel中ktime_get()方法獲取的當前時間比之前的時間晚的debug code

在Linux kernel的測試過程中,我們發現ktime_get()獲得的當前時間比之前的時間還要晚,因此我們需要在一些debug,下面介紹一下debug過程中遇到的cpu同步的問題。 Linux kernel 中ktime_get()的實現如下: ktime_t ktime_get(

solaris/unix/linux 獲取系統時間方法--精確到年月日時分秒

solaris/unix/linux下獲取系統時間的c語言方法——精確到年月日時分秒,可以用localtime函式,該函式在windows上也是通用的。 localtime函式如下: 表頭檔案 #include<time.h> 定義函式 struct tm *l

linux 獲取系統時間(兩種辦法,兩種精度

1.、寫時間到檔案裡    void get_time() {time_t now;struct tm *timenow;FILE *fp;char time_buffer[100] = {0};ti

linux 獲取本機MAC/IP地址的方法

linunx 編程 mac 地址功能:查詢本機IP/MAC地址,過濾掉127.0.0.1 loop-back 地址適用:linux, ubuntu 16.04 調試通過#include <stdlib.h>#include <stdio.h>#include <unistd.h&

linux獲取文件全路徑的方法

linux 獲取文件 全路徑 獲取路徑的各種相關方法:獲取文件名:basename /home/cuizhiliang344/note.txtnote.txt獲取目錄:dirname /home/cuizhiliang344/note.txt/home/cuizhiliang344通過一個文件獲取