linux時間子系統(四)

2.3 系統調用 

  timekeeper提供一系列的系統調用,使得用戶空間可以獲取想要的時間。下面簡單的介紹一下clock_gettime系統調用

SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,

                struct timespec __user *,tp)

{

        struct k_clock *kc = clockid_to_kclock(which_clock);

        struct timespec kernel_tp;

        int error;

 

        if (!kc)

                return -EINVAL;

 

        error = kc->clock_get(which_clock, &kernel_tp);

 

        if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))

                error = -EFAULT;

 

        return error;

}

 

static __init int init_posix_timers(void)

{

        struct k_clock clock_realtime = {

                .clock_getres   = hrtimer_get_res,

                .clock_get      = posix_clock_realtime_get,

                .clock_set      = posix_clock_realtime_set,

                .clock_adj      = posix_clock_realtime_adj,

                .nsleep         = common_nsleep,

                .nsleep_restart = hrtimer_nanosleep_restart,

                .timer_create   = common_timer_create,

                .timer_set      = common_timer_set,

                .timer_get      = common_timer_get,

                .timer_del      = common_timer_del,

        };

        struct k_clock clock_monotonic = {

                .clock_getres   = hrtimer_get_res,

                .clock_get      = posix_ktime_get_ts,

                .nsleep         = common_nsleep,

                .nsleep_restart = hrtimer_nanosleep_restart,

                .timer_create   = common_timer_create,

                .timer_set      = common_timer_set,

                .timer_get      = common_timer_get,

                .timer_del      = common_timer_del,

        };

        struct k_clock clock_monotonic_raw = {

                .clock_getres   = hrtimer_get_res,

                .clock_get      = posix_get_monotonic_raw,

        };

        struct k_clock clock_realtime_coarse = {

                .clock_getres   = posix_get_coarse_res,

                .clock_get      = posix_get_realtime_coarse,

        };

        struct k_clock clock_monotonic_coarse = {

                .clock_getres   = posix_get_coarse_res,

                .clock_get      = posix_get_monotonic_coarse,

        };

        struct k_clock clock_boottime = {

                .clock_getres   = hrtimer_get_res,

                .clock_get      = posix_get_boottime,

                .nsleep         = common_nsleep,

                .nsleep_restart = hrtimer_nanosleep_restart,

                .timer_create   = common_timer_create,

                .timer_set      = common_timer_set,

                .timer_get      = common_timer_get,

                .timer_del      = common_timer_del,

        };

        posix_timers_register_clock(CLOCK_REALTIME, &clock_realtime);

        posix_timers_register_clock(CLOCK_MONOTONIC, &clock_monotonic);

        posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);

        posix_timers_register_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse);

        posix_timers_register_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse);

        posix_timers_register_clock(CLOCK_BOOTTIME, &clock_boottime);

        posix_timers_cache = kmem_cache_create("posix_timers_cache",

                                        sizeof (struct k_itimer), 0, SLAB_PANIC, NULL);

        idr_init(&posix_timers_id);

        return 0;

}

#define CLOCK_REALTIME                  0

#define CLOCK_MONOTONIC                 1

#define CLOCK_PROCESS_CPUTIME_ID        2

#define CLOCK_THREAD_CPUTIME_ID         3

#define CLOCK_MONOTONIC_RAW             4

#define CLOCK_REALTIME_COARSE           5

#define CLOCK_MONOTONIC_COARSE          6

#define CLOCK_BOOTTIME                  7

#define CLOCK_REALTIME_ALARM            8

#define CLOCK_BOOTTIME_ALARM            9

   系統在初始化是會調用init_posix_timers等函數來初始化clock_gettime系統調用所需要的相關數據結構。這裏,調用clock_gettime獲取時間時,需要的是k_clock結構中的clock_get回調函數。對於clock_gettime的which_clock參數,系統支持獲取包括xtime,boot time,monotonic time,raw monotonic time以及進程或者線程運行時間等共十種方式。對於獲取xtime和monotonic time,which_clock有兩種設置,分別是帶_COARSE和不帶兩種方式。

2.3.1 _COARSE作用

static int posix_clock_realtime_get(clockid_t which_clock, struct timespec *tp)

{

        ktime_get_real_ts(tp);

        return 0;

}

 

#define ktime_get_real_ts(ts)   getnstimeofday(ts)

void getnstimeofday(struct timespec *ts)

{

        unsigned long seq;

        s64 nsecs;

 

        WARN_ON(timekeeping_suspended);

 

        do {

                seq = read_seqcount_begin(&xtime_seq);

 

                *ts = xtime;

                nsecs = timekeeping_get_ns();

 

                /* If arch requires, add in gettimeoffset() */

                nsecs += arch_gettimeoffset();

 

        } while (read_seqcount_retry(&xtime_seq, seq));

 

        timespec_add_ns(ts, nsecs);

}       

static inline s64 timekeeping_get_ns(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, timekeeper.mult,

                                  timekeeper.shift);

}

 

static int posix_get_realtime_coarse(clockid_t which_clock, struct timespec *tp)

{

        *tp = current_kernel_time();

        return 0;

}

struct timespec current_kernel_time(void)

{

        struct timespec now;

        unsigned long seq;

 

        do {

                seq = read_seqcount_begin(&xtime_seq);

                                                

                now = xtime;

        } while (read_seqcount_retry(&xtime_seq, seq));

        

        return now;

}

   從函數實現可以看到,當帶_COARSE後綴時,函數直接返回xtime。而不帶_COARSE後綴時,函數得首先統計當期時刻和上次更新xtime時的時間差,將時間差與xtime之和返回。從這點看,帶後綴的比不帶後綴的效率要高。當需要的時間不需要太精確時,可以使用帶_COARSE後綴的參數來獲取時間,這樣可以略微提升應用的運行速度。當獲取時間的操作很頻繁時,作用尤其明顯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章