kvm是一个内核模块,它实现了一个/dev/kvm的字符设备来与用户进行交互,通过调用一系列ioctl函数可以实现qemu和kvm之间的切换。

1、qemu发起KVM_CREATE_VM的ioctl创建虚拟机

qemu从vl.c/main开始,通过configure_accelerator根据当前current_machine调用对应的accel_init_machine,如果是kvm则具体是kvm_init。当要创建虚拟机,kvm_init函数中会s->fd = qemu_open("/dev/kvm", O_RDWR);打开/dev/kvm设备,获取虚拟机句柄fd,在该fd上ret = kvm_ioctl(s, KVM_CREATE_VM, type); s->vmfd = ret;此ioctl函数在kvm中的实现为kvm_main.c中kvm_dev_ioctl函数。当传入的参数为KVM_CREATE_VM时,该函数会创建一个VM,并且返回一个vm_fd,通过该vm_fd可以操作虚拟机。

2、qemu中创建虚拟机的vcpu和qemu线程关系,并切换到kvm中

在vl.c/main的最开始会module_call_init(MODULE_INIT_MACHINE)本质就是把pc_init1赋值给了mc->init。在kvm_init创建完虚拟机后,会返回到main中,调用machine_class->init(current_machine);即会调用之前注册的pc_init1,该函数中有两个重要的pc_cpus_initpc_memory_init,即CPU和内存的初始化,在pc_cpus_init-》pc_new_cpu-》(1)cpu_x86_create主要就是把CPUX86State填充了一下,涉及到CPUID和其他的feature。(2)object_property_set_bool-》object_property_set_qobject-》object_property_set-》property_set_bool-》device_set_realized-》dc->realize此即为X86_cpu_common_class_init设置了处理函数dc->realize = x86_cpu_realizefn;

执行x86_cpu_realizefn调用qemu_init_vcpu-》qemu_kvm_start_vcpu-》qemu_thread_create该函数创建VCPU对应的qemu线程,线程函数是qemu_kvm_cpu_thread_fn,该线程函数中:

(1)kvm_init_vcpu(1.1)通过ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)kvm_arch_vcpu_id(cpu));创建虚拟机的vcpu。对应到kvm的kvm_main.c中kvm_vm_ioctl函数,当传入的参数为VM_CREATE_VCPU时,与KVM_CREATE_VM过程类似,它创建一个vcpu并且返回可以操作该vcpu的vcpu_fd;(1.2)mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);cpu->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, cpu->kvm_fd, 0);获取kvm_run对应的内存映射(1.3)kvm_arch_init_vcpu则填充对应的kvm_arch内容。

(2)在kvm_init_vcpu返回后会先设置开关qemu_cond_signal(&qemu_cpu_cond);打开这个开关(貌似再经过pc_memory_init设置好内存后,pc_init1完成,即可运行)才会while循环kvm_cpu_exec,该函数会run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);切换到kvm中运行。对应到kvm的:kvm_main.c中kvm_vcpu_ioctl函数,若传入的参数为KVM_RUN,它最终会调用vcpu_enter_guest函数进入guest vm。

关于开关:

qemu-kvm线程工作过程:
1)启动一个子线程,创建初始化vcpu,主线程等待
2)子线程创建初始化vcpu完毕,子线程等待,并等候通知主线程运行
3)主线程继续初始化虚拟机工作,初始化完成,通知子线程继续运行
4)子线程继续启动虚拟机kvm_run,主线程执行select交互处理

3、主线程main_loop

Thread1:主线程,这个线程loop循环,循环操作select.实际就是查看有无读写文件描述符,有的话进行读写操作

Thread2:子线程,异步进行i/o操作,主要针对磁盘映像操作(block drive)

Thread3:子线程,VCPU线程, kvm_run启动和运行虚拟机

ps –ef|grep qemu

gdb –p $pid

参考:oenhen虚拟机创建和运行

qemu创建vm和vcpu进入kvm的流程的更多相关文章

  1. Qemu创建KVM虚拟机内存初始化流程

    转载请注明:[转载自博客xelatex KVM],并附本文链接.谢谢. [注]文章中采用的版本: Linux-3.11,https://www.kernel.org/pub/linux/kernel/ ...

  2. qemu启动vm后,如何host上使用ssh连接?

    qemu启动vm后,如何从host ssh连接vm? qemu启动参数 启动命令: ${cmd_qemu_system} --enable-kvm \ -machine type=q35,accel= ...

  3. openstack上创建vm实例后,状态为ERROR问题解决

    问题说明:在openstack上创建虚拟机,之前已顺利创建了n个centos6.8镜像的vm现在用ubuntu14.04镜像创建vm,发现vm创建后的状态为ERROR! 1)终端命令行操作vm创建 [ ...

  4. Azure Virtual Machine 之 如何利用Management Class Libraries 创建VM

    之前发的blog简单的介绍了如何使用Management Class Libraries 来控制Azure platform. 但由于官方并没有提供文档,所以我们只能够通过自己研究来摸索使用该类库的方 ...

  5. 从托管映像创建 VM

    可以从 Azure 中托管的 VM 映像创建多个 VM. 托管 VM 映像包含创建 VM 所需的信息,包括 OS 和数据磁盘. 构成映像的 VHD(包括 OS 磁盘和任何数据磁盘)存储为托管磁盘. 先 ...

  6. 由于挂载的nfs存储目录掉下线,导致创建VM时,无法创建

    具体错误,如下截图 重新挂载存储后,在创建VM,将成功

  7. Azure上采用Json Template从已有的VHD创建VM

    从已有的VHD创建VM是使用Azure中经常要操作的内容. 本文将介绍如何采用Json Template从已经有的VHD创建VM. 一.准备VHD 在我的Azure账户中选择一台VM,如下图: 查看其 ...

  8. kvm初体验之八:调整vm的vcpu, memory, disk大小

    假设host上创建的vm的名字为vm1. 1. 查看vm1的domain information [root@tanghuimin thm]# virsh dominfo vm1 Id: 10 Nam ...

  9. opennebula kvm 创建VM oned报错日志

    Thu Jul :: [ReM][D]: Req: UID: VirtualMachineDeploy result SUCCESS, Thu Jul :: [TM][D]: Message rece ...

随机推荐

  1. WebService的两种方式SOAP和REST有什么不同?

    REST API 优点: 1. 轻量级的解决方案,不必向SOAP那样要构建一个标准的SOAP XML. 2. 可读性比较好:可以把URL的名字取得有实际意义. 3. 不需要SDK支持:直接一个Http ...

  2. php 一行代码解决二维数组去重

    array_unique($array, SORT_REGULAR);

  3. 邮件服务器安装--Postfix + Dovecot + Squirrelmail--CentOS 6.4

    英文原文链接 : http://www.unixmen.com/install-postfix-mail-server-with-dovecot-and-squirrelmail-on-centos- ...

  4. masonry布局说明

    这个要根据情况而定,有时会很有用的. setContentHuggingPriority: 优先级越高,代表压缩越厉害,越晚被拉伸.就是上图中那人拉的力量更强. setContentCompressi ...

  5. 刀客139qq算命

    https://www.zhouyi.cc/bazi/sm/BaZi.php 好的算命网站 根据辛亥时看出来的午亥暗合没那么简单他不克你她太弱了婚姻不顺,是因为夫妻宫是财坏印是要比劫克财克财很重要 出 ...

  6. python摸爬滚打之day032 管道 数据共享 进程池

    1.进程池 当有成千上万个任务需要被执行的时候,有了进程池我们就不必去创建大量的进程. 首先,创建进程需要消耗时间,销毁进程(空间,变量,文件信息等等的内容)也需要消耗时间, 第二即便开启了成千上万的 ...

  7. Get all static wms goodlocation data

    sql function and store process: create function [dbo].[fun_splitin](@c varchar(),@split varchar()) r ...

  8. 处理 Archlinux 报错

    failed to kernel 1 sudo pacman -S linux-headers tpm_crb, uvcvideo 等错误 sudo vim /etc/modprobe.d/black ...

  9. man scp

    SCP(1)   BSD General Commands Manual   SCP(1) NAME     scp - secure copy (remote file copy program) ...

  10. 学号 20175201张驰 《Java程序设计》第6周学习总结

    学号 20175201张驰 <Java程序设计>第6周学习总结 教材学习内容总结 第7章 ·1.Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类称为内部类的外嵌类 ...