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

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

上一节,我们讲了一下虚拟化的基本原理,以及 qemu、kvm 之间的关系。这一节,我们就来看一下,用户态的 qemu 和内核态的 kvm 如何一起协作,来创建虚拟机,实现 CPU 和内存虚拟化。
这里是上一节我们讲的 qemu 启动时候的命令。
qemu-system-x86_64 -enable-kvm -name ubuntutest -m 2048 -hda ubuntutest.qcow2 -vnc :19 -net nic,model=virtio -nettap,ifname=tap0,script=no,downscript=no
接下来,我们在这里下载qemu 的代码。qemu 的 main 函数在 vl.c 下面。这是一个非常非常长的函数,我们来慢慢地解析它。

1. 初始化所有的 Module

第一步,初始化所有的 Module,调用下面的函数。
module_call_init(MODULE_INIT_QOM);
上一节我们讲过,qemu 作为中间人其实挺累的,对上面的虚拟机需要模拟各种各样的外部设备。当虚拟机真的要使用物理资源的时候,对下面的物理机上的资源要进行请求,所以它的工作模式有点儿类似操作系统对接驱动。驱动要符合一定的格式,才能算操作系统的一个模块。同理,qemu 为了模拟各种各样的设备,也需要管理各种各样的模块,这些模块也需要符合一定的格式。
定义一个 qemu 模块会调用 type_init。例如,kvm 的模块要在 accel/kvm/kvm-all.c 文件里面实现。在这个文件里面,有一行下面的代码:
type_init(kvm_type_init);
#define type_init(function) module_init(function, MODULE_INIT_QOM)
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_module_init(function, type); \
}
void register_module_init(void (*fn)(void), module_init_type type)
{
ModuleEntry *e;
ModuleTypeList *l;
e = g_malloc0(sizeof(*e));
e->init = fn;
e->type = type;
l = find_type(type);
QTAILQ_INSERT_TAIL(l, e, node);
}
从代码里面的定义我们可以看出来,type_init 后面的参数是一个函数,调用 type_init 就相当于调用 module_init,在这里函数就是 kvm_type_init,类型就是 MODULE_INIT_QOM。是不是感觉和驱动有点儿像?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(10)

  • 最新
  • 精选
  • 大王叫我来巡山
    感觉设计这个软件的真厉害,怪不得我们自己做的业务系统自己都信不过,差距实在是太远,国内很多大公司在分享技术的时候也就是个PPT,根本不敢把代码放出来给大家看,也没有把实际用的效果展示给大家,只是给别人的感觉很牛逼而已。我感觉我从事这个工作这么久,真没遇到过这种大神

    作者回复: 是的,绝对牛

    27
  • 佳俊
    看了很久都没有搞明白一个type_init 宏定义出来的函数是怎么被调用的,直到发现在module_init 里面一个这个属性的定义__attribute__((constructor)),才明白是GNU C 里面的一个特性,在main函数调用前系统会自动先调用这个函数。

    作者回复: 是的

    7
  • 泡泡
    请问代码是用的哪个内核版本

    作者回复: 4.13

    2
    1
  • why
    解析 qemu 的执行步骤 1. 初始化所有模块 模块的信息(包括名称, 模块类型初始化函数等), 存在 TypeInfo 中, 通过调用 type_init, 将这些信息统一以 ModelEntry 的格式存储到 ModelTypeList 中. module_call_init() 会调用 ModelTypeList 中所有模块的初始化函数, 从 ModelEntry 里存储的 TypeInfo 信息生成 TypeImpl(类似于 class 文件), 这个 TypeImpl 会存储到 qemu 的一个全局 hash 表中. 2. 解析命令行参数 命令行参数比较多. 其中 -machine 参数用于指定计算机体系结构. 另外 网卡/硬盘的配置要分表从 Host/Guest 较多进行设置. 3. 初始化 machine 会在 qemu 的全局 hash 表中注册对应计算机体系结构的 TypeImpl 信息. 然后会调用所有 TypeImpl 的初始化方法 class_init 生成对应的 Class. 最后会得到一个 MachineClass. 然后调用 TypeImple 中的 instance_init 方法生成 MachineClass 的一个实例.
    12
  • 石维康
    请问老师pc_machine_type_##suffix所对应的TypeImpl的instance_init是在哪初始化的?也就是从代码里如何体现从MachineClass生成MachineState?
    3
  • robin
    期望老师出一个讲openstack的专栏
    2
  • 柒城
    老师,之后会不会开个专门讲虚拟化的专栏啊?吧QEMU和KVM好好讲讲
    1
  • robin
    openstack是调用libvirt,libevirtd再调用kvm吗?
    1
  • kkxue
    nova通过libvirt驱动,将配置数据转化成XML格式的文件,用于创建虚拟机。
  • 奔跑的码仔
    请问,qemu使用的是哪个版本?
收起评论
显示
设置
留言
10
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部