做网站需要icp经营许可证,cuteftp 备份网站,某个网站访问慢的原因,网站关键词选取的步骤在云主机环境涉及到时间处理#xff0c;虚拟机vmexit#xff0c;内部时间中断模拟处理#xff0c;电路板通常有一些定时操作设备#xff0c;hyperson里如何实现#xff0c;怎么保证时间可靠#xff1f; 代码#xff1a;qemu-5.0 1、qemu时钟#xff08;time.h#xff… 在云主机环境涉及到时间处理虚拟机vmexit内部时间中断模拟处理电路板通常有一些定时操作设备hyperson里如何实现怎么保证时间可靠 代码qemu-5.0 1、qemu时钟time.h 此处时间被分为四类 真实时间即使vm停了也会运行用于不改变虚拟机状态的内容 虚拟时间vm停时间停用于vm运行期 宿主机时间主机时间源设备虚拟机挂起时也会运行反应系统时间改变比如NTP 虚拟运行时时间虚拟机运行时在icount模式下计时在vcpu睡眠时增加虚拟时间 typedef enum {QEMU_CLOCK_REALTIME 0, //QEMU_CLOCK_VIRTUAL 1,QEMU_CLOCK_HOST 2,QEMU_CLOCK_VIRTUAL_RT 3,QEMU_CLOCK_MAX
} QEMUClockType;int64_t now qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); //获取当前时间定时器 qemu提供ms、ns级别定时器timer_xxx函数进行创建、删除、重置、改变可以把定时器加到不同的时钟上。 eg创建定时器只在vcpu运行时计时当经过duration毫秒时执行回调 QEMUTimer *user_timer timer_new_ms(QEMU_CLOCK_VIRTUAL, user_timeout_cb, obj);
int64_t now qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);timer_mod(timer, now duration);static void user_timeout_cb(void *opaque)
{obj_t *obj (obj_t*)opaque;
...
}定时器设备 设备的两部分IO内存IRQ中断需要实现qemu用内部时钟模型在硬件上表现 CPIOM tick timer示例 typedef struct cpiom_clock
{QEMUTimer *qemu_timer;uint32_t *trigger;int64_t restart;double duration;} cpiom_clock_t;typedef struct cpiom_timer_device_state
{/* private */SysBusDevice parent_obj; /* public */MemoryRegion iomem;cpiom_timer_reg_t reg;qemu_irq irq; /* internal clock management */cpiom_clock_t tick;} cpiom_timer_state_t;cpiom定时器包含一个IO内存区域iomem、底层设备寄存器reg、一个时钟tick 真正的CPIOM计时器复杂一些我们仅展示一个计时器实现。 static void cpiom_timer_init(Object *obj)
{cpiom_timer_state_t *tm CPIOM_TIMERS(obj);SysBusDevice *dev SYS_BUS_DEVICE(obj); memory_region_init_io(tm-iomem, obj, cpiom_timer_reg_ops, tm,CPIOM_TIMERS_NAME-reg, CPIOM_MMAP_TIMERS_SIZE);sysbus_init_mmio(dev, tm-iomem);sysbus_init_irq(dev, tm-irq); tm-tick.qemu_timer timer_new_ns(QEMU_CLOCK_VIRTUAL, tick_expired, tm);tm-tick.trigger tm-reg.base.tick;
...
}设备初始化由于cpiom_timer_reg_ops 有回调任何tm-iomem的访问都会更新tm-reg。同时创建一个纳秒定时器调用tick_expired 访问CPIO计时器 我们设置offset 0x0c is a R/W 32 bits 作为TIME_COUNTER 寄存器当值为0触发irq 实现一个驱动程序通过写寄存器设置定时 static const MemoryRegionOps cpiom_timer_reg_ops {.read cpiom_timer_reg_read,.write cpiom_timer_reg_write,.endianness DEVICE_NATIVE_ENDIAN,
};static void cpiom_timer_reg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
{
....cpiom_timer_state_t *tm (cpiom_timer_state_t*)opaque; if (addr 0x0c)write_counter(tm, data);
....
}static void write_counter(cpiom_timer_state_t *tm, uint32_t new)
{if (!timer_is_active(tm))return; if (new 0)tick_expired((void*)tm);elseclock_setup(tm, tm-tick, new);
}static void tick_expired(void *opaque)
{cpiom_timer_state_t *tm (cpiom_timer_state_t*)opaque;qemu_irq_raise(tm-irq);
}当写设备时判断计数到期到期就触发irq没到就更新计数 时间膨胀更新计数 static void clock_setup(cpiom_timer_state_t *tm, cpiom_clock_t *clk, uint32_t count)
{clk-duration nsperiod * count;clk-restart qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t expire clk-restart (int64_t)floor(clk-duration);timer_mod(clk-qemu_timer, expire /* /- speed factor */);
}nsperiod (1/TIMER_FREQ_MHZ) * 1000 * scale; 经过的时间 now qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);count (now - clk-restart)/nsperiod;clk-restart now;每当驱动读寄存器vm必须放映经过的时间。