欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

qemu虚拟机的实时时钟从哪里来

程序员文章站 2022-05-29 22:34:15
...

对于物理机而言时间是实时时钟(rtc)+启动后时间(boot up time)的和。rtc一般是存在于cmos存储中,它是一个类似于flash的东西,掉电不失,可读写的存储空。rtc存储在里面,每次机器启动的时候读一次就知道机器刚刚启动时的时间了。

对于虚机要想知道启动时的时间就需要vmm提供类似于rtc的东西。也就是模拟rtc设备。对于qemu-kvm虚拟机,qemu就负责模拟rtc。

qemu模拟rtc是非常容易的事情,只需创建一个rtc的数据结构,再给它一块内存用来读写,初始时间就从主机上获取。看代码:

static void rtc_realizefn(DeviceState *dev, Error **errp)
{
    ISADevice *isadev = ISA_DEVICE(dev);
    RTCState *s = MC146818_RTC(dev);
    int base = 0x70;
...
    rtc_set_date_from_host(isadev);
...
memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2);
...
}

rtc_readlizefn负责实现rtc初始化,rtc_set_date_from_host 负责获取时间并写入设备数据结构。最后memory_region_init_io负责给初始化好的rtc设备分配内存,以后这块内存就作为rtc设备的主体使用了。

static void rtc_set_date_from_host(ISADevice *dev)
{
    RTCState *s = MC146818_RTC(dev);
    struct tm tm;

    qemu_get_timedate(&tm, 0);

    s->base_rtc = mktimegm(&tm);
    s->last_update = qemu_clock_get_ns(rtc_clock);
    s->offset = 0;

    /* set the CMOS date */
    rtc_set_cmos(s, &tm);
}

RTCState就是rtc的数据结构。

int64_t qemu_clock_get_ns(QEMUClockType type)
{
    int64_t now, last;
    QEMUClock *clock = qemu_clock_ptr(type);

    switch (type) {
    case QEMU_CLOCK_REALTIME:
        return get_clock();
    default:
    case QEMU_CLOCK_VIRTUAL:
    case QEMU_CLOCK_VIRTUAL_EXT:
        if (use_icount) {
            return cpu_get_icount();
        } else {
            return cpu_get_clock();
        }
    case QEMU_CLOCK_HOST:
        now = REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime());
        last = clock->last;
        clock->last = now;
        if (now < last || now > (last + get_max_clock_jump())) {
            notifier_list_notify(&clock->reset_notifiers, &now);
        }
        return now;
...
}

最终qemu调用gettimeofday来获取主机时间。这就是rtc模拟的主要流程。

 

 

相关标签: 虚拟化