linux时间子系统之,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后缀的参数来获取时间,这样可以略微提升应用的运行速度。当获取时间的操作很频繁时,作用尤其明显。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值