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後綴的參數來獲取時間,這樣可以略微提升應用的運行速度。當獲取時間的操作很頻繁時,作用尤其明顯。 |
linux時間子系統(四)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.