android时区的初始化

时间:2022-06-07 20:35:47

                                                           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