qemu-kvm 线程事件模型 【QEMU-KVM代码分析之三】

qemu-kvm 线程事件模型
1.主(父)线程。
主线程执行循环,主要做三件事情
1).执行select操作,查询文件描述符有无读写操作
2).执行定时器回调函数
3).执行下半部(BH)回调函数。为什么要采用BH,资料说主要避免可重入性和调用栈溢出。

2.执行客户机代码的线程
只讨论kvm执行客户机代码情况(不考虑TCG,TCG采用动态翻译技术),如果有多个vcpu,就意味着存在多个线程。

3.异步io文件操作线程
提交i/o操作请求到队列中, 该线程从队列取请求,并进行处理。

4.主线程与执行客户机代码线程同步
主线程与执行客户机代码线程不能同时运行,主要通过一个全局互斥锁实现。


代码分析

1.主(父)线程。
下面函数是主线程主要执行函数:当文件描述符,定时器,下半部分触发相应事件后,将执行相应回调函数。
void main_loop_wait(int timeout){
  ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
 if (ret > 0) {
        IOHandlerRecord *pioh;
        QLIST_FOREACH(ioh, &io_handlers, next) {
            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
                ioh->fd_read(ioh->opaque);
                if (!(ioh->fd_read_poll && ioh->fd_read_poll(ioh->opaque)))
                    FD_CLR(ioh->fd, &rfds);
            }
            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
                ioh->fd_write(ioh->opaque);
            }
        }
    }

  qemu_run_timers(&active_timers[QEMU_CLOCK_HOST],
                    qemu_get_clock(host_clock));

   /* Check bottom-halves last in case any of the earlier events triggered
       them.  */
    qemu_bh_poll();
}

对于select函数轮循文件描述符,以及对于该描述执行操作函数,主要通过qemu_set_fd_handler()和qemu_set_fd_handler2函数添加完成的。
int qemu_set_fd_handler(int fd,
                        IOHandler *fd_read,
                        IOHandler *fd_write,
                        void *opaque);
int qemu_set_fd_handler2(int fd,
                         IOCanRWHandler *fd_read_poll,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
                         void *opaque)

对于到期执行的定时器函数,回调函数由qemu_new_time函数添加的,触发时间qemu_mod_timer函数修改的
EMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)

下半部要添加调度函数由qemu_bh_new 和qemu_bh_schedule完成的。
EMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
void qemu_bh_schedule(QEMUBH *bh)


2.执行客户机代码的线程
当初始化客户机硬件时,对于每个cpu创建一个线程,每个线程执行ap_main_loop函数,该函数运行kvm_run函数,运行客户机代码。

/* PC hardware initialisation */
static void pc_init1(ram_addr_t ram_size,
                     const char *boot_device,
                     const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     const char *cpu_model,
                     int pci_enabled)
{
 for (i = 0; i < smp_cpus; i++) {
        env = pc_new_cpu(cpu_model);
    }

}

void kvm_init_vcpu(CPUState *env)
{
    pthread_create(&env->kvm_cpu_state.thread, NULL, ap_main_loop, env);

    while (env->created == 0)
        qemu_cond_wait(&qemu_vcpu_cond);
}
执行客户机线程调用函数ap_main_loop,该函数最终调用函数kvm_main_loop_cpu, 该函数工作过程如下:
1.注入中断,执行客户机代码,解决客户机退出原因,例如 KVM_EXIT_MMIO, KVM_EXIT_IO。如果解决成功,继续运行。失败话,进入步骤2 
2.该步骤如果vcpu存在着,已传递但是还没有处理里信号SIG_IPI,SIGBUS,该线程阻塞,也就意味着暂停处理器客户机代码,直到处理相应信号。
3.如果上述过程完成后,继续允许执行客户机代码。
static int kvm_main_loop_cpu(CPUState *env)
{
    while (1) {
        int run_cpu = !is_cpu_stopped(env);
        if (run_cpu && !kvm_irqchip_in_kernel()) {
            process_irqchip_events(env);
            run_cpu = !env->halted;
        }
        if (run_cpu) {
            kvm_cpu_exec(env);
            kvm_main_loop_wait(env, 0);
      
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值