这个函数主要用于读取kernel时间,如果是superuser的话,则可以写kernel时间。
其源码分析如下:
SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
{
struct timex txc; /* Local copy of parameter */
int ret;
/* Copy the user data space into the kernel copy
* structure. But bear in mind that the structures
* may change
*/
#从user space copy txc_p中的内容到txc中
if (copy_from_user(&txc, txc_p, sizeof(struct timex)))
return -EFAULT;
#根据txc中的内容读写kernel时间
ret = do_adjtimex(&txc);
#从kernel space 中的txc中的内容copy到txc_p中
return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
}
int do_adjtimex(struct timex *txc)
{
#得到timer keeper的时间
struct timekeeper *tk = &tk_core.timekeeper;
unsigned long flags;
struct timespec64 ts;
s32 orig_tai, tai;
int ret;
/* Validate the data before disabling interrupts */
#检查txc 中的时间是否合法
ret = timekeeping_validate_timex(txc);
if (ret)
return ret;
#ADJ_SETOFFSET 表示增加当前time keeper的时间
if (txc->modes & ADJ_SETOFFSET) {
struct timespec64 delta;
delta.tv_sec = txc->time.tv_sec;
delta.tv_nsec = txc->time.tv_usec;
if (!(txc->modes & ADJ_NANO))
delta.tv_nsec *= 1000;
ret = timekeeping_inject_offset(&delta);
#正常情况下ret等于零。
if (ret)
return ret;
}
#以timespec64格式获取当前时间
getnstimeofday64(&ts);
#开始修改time keeper时间
raw_spin_lock_irqsave(&timekeeper_lock, flags);
write_seqcount_begin(&tk_core.seq);
orig_tai = tai = tk->tai_offset;
#根据txc和ts的时间来或者写 kernel 时间,主要给txc赋值,并通过process_adjtime_modes得到tail
ret = __do_adjtimex(txc, &ts, &tai);
#说明时间已经被更新了,开始update time keeper中的时间
if (tai != orig_tai) {
__timekeeping_set_tai_offset(tk, tai);
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
}
tk_update_leap_state(tk);
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
if (tai != orig_tai)
clock_was_set();
#通知ntp时间已经被修改
ntp_notify_cmos_timer();
return ret;
}
系统调用之sys_adjtimex
最新推荐文章于 2022-03-25 22:43:25 发布