linux源码解读 kernel/time.c

asmlinkage long sys_time(time_t __user * tloc)
{
	time_t i;
	struct timeval tv;

	do_gettimeofday(&tv);
	i = tv.tv_sec;

	if (tloc) {
		if (put_user(i,tloc))
			i = -EFAULT;
	}
	return i;
}

time系统调用的具体实现。
time返回1970-01-01 00:00:00 UTC起经过的时间。如果在中国时间要加上8个小时、

struct timeval {
	time_t		tv_sec;		/* seconds 秒*/
	suseconds_t	tv_usec;	/* microseconds 微秒(百万分之一秒)*/
};

调用do_gettimeofday函数获取秒数和微秒数,并将秒数送到返回值和参数中。

asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz)
{
	if (likely(tv != NULL)) {
		struct timeval ktv;
		do_gettimeofday(&ktv);
		if (copy_to_user(tv, &ktv, sizeof(ktv)))
			return -EFAULT;
	}
	if (unlikely(tz != NULL)) {
		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
			return -EFAULT;
	}
	return 0;
}

获取秒数与微秒数,时区。这些信息。
do_gettimeofday函数获取秒数与微秒数。tz获取时区信息。

struct timezone {
	int	tz_minuteswest;	/* minutes west of Greenwich 格林威治以西几分钟*/
	int	tz_dsttime;	/* type of dst correction */
};

do_gettimeofday函数来自于arch/i386/kernel/time.c

/*
 * This version of gettimeofday has microsecond resolution
 * and better than microsecond precision on fast x86 machines with TSC.
 * 这个版本的gettimeofday有微秒的分辨率,并且在配备TSC的fast x86机器上,精度优于微秒。
 */
void do_gettimeofday(struct timeval *tv)
{
	unsigned long seq;
	unsigned long usec, sec;
	unsigned long max_ntp_tick;

	do {
		unsigned long lost;

		seq = read_seqbegin(&xtime_lock);

		usec = cur_timer->get_offset();
		lost = jiffies - wall_jiffies;

		/*
		 * If time_adjust is negative then NTP is slowing the clock
		 * so make sure not to go into next possible interval.
		 * Better to lose some accuracy than have time go backwards..
		 */
		if (unlikely(time_adjust < 0)) {
			max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
			usec = min(usec, max_ntp_tick);

			if (lost)
				usec += lost * max_ntp_tick;
		}
		else if (unlikely(lost))
			usec += lost * (USEC_PER_SEC / HZ);

		sec = xtime.tv_sec;
		usec += (xtime.tv_nsec / 1000);
	} while (read_seqretry(&xtime_lock, seq));

	while (usec >= 1000000) {
		usec -= 1000000;
		sec++;
	}

	tv->tv_sec = sec;
	tv->tv_usec = usec;
}

你可能感兴趣的:(linux源码解析)