android时区的初始化
android时区的初始化是init进程执行init.rc的解析,找到关键字sysclktz ,和参数0,调用settimeofday(NULL, &tz)将时区设置为0时区。参数时间区域为NULL,表示仅仅改变时区。
init.rc
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_adj -16
start ueventd
# create mountpoints
mkdir /mnt 0775 root system
on init
sysclktz 0
loglevel 3
# setup the global environment
export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
export LD_LIBRARY_PATH /vendor/lib:/system/lib
export ANDROID_BOOTLOGO 1
;
;
;
在init.c 执行下面的代码就触发init,执行init action的一系列操作
action_for_each_trigger("init", action_add_queue_tail);
on init
sysclktz 0 的作用是init被触发就设置时区为0
1,
system/core/init/keywords.h
keywords.h
KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
2,
init_parser.c
int lookup_keyword(const char *s)
{
case 's':
if (!strcmp(s, "ervice")) return K_service;
if (!strcmp(s, "etenv")) return K_setenv;
if (!strcmp(s, "etkey")) return K_setkey;
if (!strcmp(s, "etprop")) return K_setprop;
if (!strcmp(s, "etrlimit")) return K_setrlimit;
if (!strcmp(s, "ocket")) return K_socket;
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
if (!strcmp(s, "ymlink")) return K_symlink;
;
;
if (!strcmp(s, "ysclktz")) return K_sysclktz;
break;
}
3,
system/core/init/builtins.c
builtins.c 调用系统调用settimeofday设置时区
int do_sysclktz(int nargs, char **args)
{
struct timezone tz;
if (nargs != 2)
return -1;
memset(&tz, 0, sizeof(tz));
tz.tz_minuteswest = atoi(args[1]);
if (settimeofday(NULL, &tz))
return -1;
return 0;
}
4,
kernel/kernel/time.c
/*
* In case for some reason the CMOS clock has not already been running
* in UTC, but in some local time: The first time we set the timezone,
* we will warp the clock so that it is ticking UTC time instead of
* local time. Presumably, if someone is setting the timezone then we
* are running in an environment where the programs understand about
* timezones. This should be done at boot time in the /etc/rc script,
* as soon as possible, so that the clock can be set right. Otherwise,
* various programs will get confused when the clock gets warped.
*/
int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
{
static int firsttime = 1;
int error = 0;
if (tv && !timespec_valid(tv))
return -EINVAL;
error = security_settime(tv, tz);
if (error)
return error;
if (tz) {
/* SMP safe, global irq locking makes it work. */
sys_tz = *tz;
update_vsyscall_tz();
if (firsttime) {
firsttime = 0;
if (!tv)
warp_clock();
}
}
if (tv)
{
/* SMP safe, again the code in arch/foo/time.c should
* globally block out interrupts when it runs.
*/
return do_settimeofday(tv);
}
return 0;
}
SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
struct timezone __user *, tz)
{
struct timeval user_tv;
struct timespec new_ts;
struct timezone new_tz;
if (tv) {
if (copy_from_user(&user_tv, tv, sizeof(*tv)))
return -EFAULT;
new_ts.tv_sec = user_tv.tv_sec;
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
}
if (tz) {
if (copy_from_user(&new_tz, tz, sizeof(*tz)))
return -EFAULT;
}
return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
}
/*
* Adjust the time obtained from the CMOS to be UTC time instead of
* local time.
*
* This is ugly, but preferable to the alternatives. Otherwise we
* would either need to write a program to do it in /etc/rc (and risk
* confusion if the program gets run more than once; it would also be
* hard to make the program warp the clock precisely n hours) or
* compile in the timezone information into the kernel. Bad, bad....
*
* - TYT, 1992-01-01
*
* The best thing to do is to keep the CMOS clock in universal time (UTC)
* as real UNIX machines always do it. This avoids all headaches about
* daylight saving times and warping kernel clocks.
*/
static inline void warp_clock(void)
{
struct timespec adjust;
adjust = current_kernel_time();
adjust.tv_sec += sys_tz.tz_minuteswest * 60;
do_settimeofday(&adjust);
}
settimeofday 是可以修改系统时间,但是cmos时间改不了
date可以改cmos
由于通过settimeofday()只能设置软件时钟,并不能真正设置cmos时钟,
可以通过system("hwclock --utc -w")来把软件时钟写入到cmos里去。
但是实验发现时间较长,需要1s钟左右。
date.c中有date命令的实现。发现其实现非常简单:
date.c: main()->stime()->settimeofday() 这个settimeofday
kernel/time.c