趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
85459 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

51 | 计算虚拟化之CPU(下):如何复用集团的人力资源?

记录退出虚拟机模式的原因
退出客户机模式,保存客户机寄存器,加载宿主机寄存器
进入客户机模式运行
保存宿主机寄存器,加载客户机寄存器
运行虚拟机CPU
包含VMCS用于状态切换
在内核的KVM中创建struct vcpu_vmx结构
调用kvm_vcpu_ioctl(KVM_RUN)
调用kvm_vm_ioctl(KVM_CREATE_VCPU)
调用CPU类的初始化函数
qemu_kvm_cpu_thread_fn
pc_new_cpu
类初始化函数
继承关系
TypeImpl
TypeInfo
创建虚拟CPU线程
初始化CPU
定义CPU类型
CPU虚拟化过程

该思维导图由 AI 生成,仅供参考

上一节 qemu 初始化的 main 函数,我们解析了一个开头,得到了表示体系结构的 MachineClass 以及 MachineState。

4. 初始化块设备

我们接着回到 main 函数,接下来初始化的是块设备,调用的是 configure_blockdev。这里我们需要重点关注上面参数中的硬盘,不过我们放在存储虚拟化那一节再解析。
configure_blockdev(&bdo_queue, machine_class, snapshot);

5. 初始化计算虚拟化的加速模式

接下来初始化的是计算虚拟化的加速模式,也即要不要使用 KVM。根据参数中的配置是启用 KVM。这里调用的是 configure_accelerator。
configure_accelerator(current_machine, argv[0]);
void configure_accelerator(MachineState *ms, const char *progname)
{
const char *accel;
char **accel_list, **tmp;
int ret;
bool accel_initialised = false;
bool init_failed = false;
AccelClass *acc = NULL;
accel = qemu_opt_get(qemu_get_machine_opts(), "accel");
accel = "kvm";
accel_list = g_strsplit(accel, ":", 0);
for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
acc = accel_find(*tmp);
ret = accel_init_machine(acc, ms);
}
}
static AccelClass *accel_find(const char *opt_name)
{
char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
g_free(class_name);
return ac;
}
static int accel_init_machine(AccelClass *acc, MachineState *ms)
{
ObjectClass *oc = OBJECT_CLASS(acc);
const char *cname = object_class_get_name(oc);
AccelState *accel = ACCEL(object_new(cname));
int ret;
ms->accelerator = accel;
*(acc->allowed) = true;
ret = acc->init_machine(ms);
return ret;
}
在 configure_accelerator 中,我们看命令行参数里面的 accel,发现是 kvm,则调用 accel_find 根据名字,得到相应的纸面上的 class,并初始化为 Class 类。
MachineClass 是计算机体系结构的 Class 类,同理,AccelClass 就是加速器的 Class 类,然后调用 accel_init_machine,通过 object_new,将 AccelClass 这个 Class 类实例化为 AccelState,类似对于体系结构的实例是 MachineState。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入解析了CPU虚拟化的技术细节,从qemu初始化的main函数开始,详细解析了块设备和计算虚拟化的加速模式。重点介绍了KVM的初始化过程,包括用户态到内核态的KVM操作,以及创建虚拟机的过程。文章还介绍了网络设备的初始化过程。通过代码解析的方式,深入浅出地介绍了CPU虚拟化的多层继承关系、实例初始化过程,以及KVM内核模块的文件操作和vcpu创建过程。此外,还详细解释了EPT、VMCS的作用,以及VM-Entry和VM-Exit的重要性。总体而言,本文对于想要深入了解CPU虚拟化技术细节的读者具有很高的参考价值。文章内容涉及了CPU虚拟化的复杂过程,从定义CPU类型到虚拟CPU的创建和运行过程,以及内核中KVM的相关操作。此外,还涉及了文件系统在KVM操作中的重要性。文章通过深入的技术分析,为读者提供了全面的CPU虚拟化技术细节,适合对此感兴趣的读者深入学习。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(8)

  • 最新
  • 精选
  • whiledoing
    老师,想问一下:在虚拟机中创建的线程,是如何进行调度的?又是如何映射到vCPU执行的呢?

    作者回复: 虚拟机里面的线程分配到vcpu的过程和物理机线程的过程是一样的。虚拟机里面的线程是意识不到这是vcpu的。只不过vcpu还有被分配物理cpu才能使用,这是qemu-kvm做的事情

    2019-08-23
    4
  • 安排
    老师,那在虚拟机里面创建的多个核其实是假的是码?即使创建4个核的虚拟机,那么对应到kvm里面其实也是一个线程,也就是从虚拟机os这个层面它是无法真正利用多核的。其实它虚拟机os利用多核也没有意义。只要保证宿主os能正常利用多核就足够了,不知道这样理解是否正确?

    作者回复: 不是,虚拟机的多个核是多个线程。但是线程在物理机上能不能分到物理核,是物理机的操作系统定的。

    2019-07-28
    4
  • 小龙的城堡
    深入内核以后,发现一切都是那么简洁,美妙?

    作者回复: 绝对美妙

    2019-07-24
    4
  • 一笔一画
    .unlocked_ioctl = kvm_dev_ioctl, .compat_ioctl = kvm_dev_ioctl, 请问下这两个ioctl有什么区别?在什么时候会调到

    作者回复: 主流是unlocked_ioctl,为了兼容过去才有的compat_ioctl

    2019-07-27
    1
  • why
    CPU 虚拟化 初始化表示体系结构的 MachineClass 之后, qemu main 函数将继续初始化块设备, 初始化 KVM, 初始化网络设备以及 CPU 和 内存的虚拟化. 初始化 KVM 以类似的方式创建 AccelClass 和 AccelState. 接着调用 AccelState 中的 kvm_init 继续初始化. 打开 /dev/kvm 字符设备文件以调用 KVM 的接口. 通过 ioctl 系统调用进入内核态. 在内核态中, 调用 kvm_dev_ioctl_create_vm 创建虚拟机. 先创建 struct kvm 表示虚拟机, 其中存储 vcpu, mm_struct 等信息. 再创建 fd, file_operations 设为 kvm_vm_fops 完成 kvm 内核数据结构的创建 CPU 虚拟化 调用 MachineClass 的 init 函数. 里面调用 pc_cpus_init 和 pc_memory_init 分别进行 vcpu 和内存的虚拟化. 从 qemu 参数解析得到 CPU 类型, 得到对应虚拟化 CPU 的定义. 调用定义中的初始化函数, 会设置 realize 函数 x86_cpu_realizefn, 在 x86_cpu_realizefn 会为一个 vcpu 创建一个线程. 该线程执行 qemu_kvm_cpu_thread_fn 函数. qemu_kvm_cpu_thread_fn 先初始化 vcpu, 创建一个 struct file, file_operation 指向 kvm_vcpu_fops. 然后在 vmx_create_cpu 创建标识 vcpu 的结构 vcpu_vmx. vcpu_vmx 包含 guest_msrs, loaded_vmcs 等. vmcs 存储 vcpu 状态, 物理 cpu 状态等信息. 对 vmcs 有两个操作 VM_Entry 进入 guest 状态, vm_exit 进入宿主机状态. qemu_kvm_cpu_thread_fn 接着执行无限循环调用 kvm_cpu_exec. 在 kvm_cpu_exec 进入 vm_entry, 执行 kvm_vcpu_ioctl(KVM_RUN) , 进行无限循环进入 guest 运行或处理信号. 进入 guest 执行的步骤为 save host reg -> load guest reg -> 进入/恢复 guest 模式运行, 退出时 save guest reg -> load host reg.
    2020-02-26
    7
  • 陈 皮。
    老师,请问是不是虚拟机的CPU本质就是一个线程,物理机的CPU调度到这个线程就等于调度到对应的VCPU?
    2019-09-25
    1
  • Geek_ae11ce
    切换到kvm_init_vcpu那段,最好能再贴函数一下代码。上下翻来翻去特别费劲且不易于理解。
    2023-07-26归属地:北京
  • 阳光梦
    超哥,请问openvswitch结合dpdk跑在宿主机上时,qemu~kvm的虚拟机使用virtio虚拟网卡支持对称rss?想跑fstack程序。
    2020-10-25
收起评论
显示
设置
留言
8
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部