Libvirt同步机制 —— 设计原理

本文深入剖析Libvirt虚拟机管理的同步原理,包括VM同步如何确保数据一致性,以及任务同步、异步任务和嵌套异步任务的设计与执行流程。通过实例详细阐述了不同任务类型在并发执行时的锁机制和信号量协调,展示了Libvirt如何高效并发处理API请求,同时保证任务执行顺序和数据安全。

背景

  • Libvirt是一个虚拟机管理的开源项目,它的实现涉及到对虚拟机任务的管理,为了提高Libvirtd服务并发执行API的效率,同时又能保证多线程访问同一个虚机数据结构的一致性,Libvirt基于不同场景设计实现了不同粒度的同步机制,本文主要分析这些同步机制的设计原理。

VM同步原理

  • virDomainObj是Libvirt对虚机数据结构的抽象,包含了通用信息(比如虚机xml加载到内存信息)和每个虚机私有的driver信息(比如qemu driver的私有qemuDomainObjPrivate)。当多个API同时发起,可能出现多线程并发修改VM信息的场景,virDomainObj的基类parent中包含一把互斥锁virMutex,多线程访问VM时通过这把锁来保证数据同步。下图是一个示例,解释两个Libvirt的API qemuDomainGetInfo并发执行时的加锁顺序。
    请添加图片描述
  • 如上图所示,thread1是Libvirtd服务收到客户端的rpc调用后fork的线程,开始执行qemuDomainGetInfo,这个API的功能是获取虚机的内存、CPU运行状态等信息,这些信息在VM的结构体中都有保存,因此API的主要逻辑就是查询VM的数据结构。
  • 步骤如下:
  1. 通过qemuDomainObjFromDomain接口获取vm结构体,过程中对virDomainObj.parent加锁
  2. 获取虚机总内存:virDomainObj.def->mem.total_memory
  3. 获取虚机状态:virDomainObj.state.state
  4. 获取proc文件系统下虚机Qemu进程运行时间
  5. 通过virDomainObjEndAPI释放virDomainObj.parent锁
  • 以上步骤中,所有Libvirt API都必须执行1、5这两部,保证所有API对VM数据结构的视图一致。
  • 现在假设Libvirtd服务在API执行过程中又收到了客户端的rpc调用消息,针对同一个虚机开始执行qemuDomainGetInfo,由于Libvirt API编程规范中要求在修改VM信息前必须先获取virDomainObj.parent锁,而此时virDomainObj.parent锁被先前的API持有,因此后来的API只能等待先前API执行结束,释放锁之后才能开始。

任务同步原理

  • VM同步保证了虚机信息在多线程修改时保持一致,但有的时候,针对虚机的一些操作是比较耗时的,并且时间开销不在对数据结构的修改上,而是其它动作,比如执行QMP、QGA等命令或者执行迁移、备份这种操作。这个时候VM同步的接口会显得粒度太大,需要允许在以上这些操作的同时,其它API也能并发执行。因此,Libvirt设计了针对虚机的任务同步机制和接口并定义了一系列同步任务,对于同一个虚机而言,同一时间只允许有其中一个任务在执行。

同步任务

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

享乐主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值