Libvirt代码架构
Libvirt介绍
Libvirt学习
- 通过virsh了解libvirt api的调用方式
- 通过virHypervisorDriver了解libvirt api的实现
virsh代码阅读
通过阅读virsh代码我们能够了解libvirt api的作用以及调用方法
| 文件名 | 对应vshCmdDef变量 | 对应virsh命令 |
|---|---|---|
| virsh-domain-monitor.c | domMonitoringCmds | virsh XX(虚拟机监控) |
| virsh-domain.c | domManagementCmds | virsh XX(虚拟机操作) |
| virsh-host.c | hostAndHypervisorCmds | virsh XX(虚拟机配置) |
| virsh-interface.c | ifaceCmds | virsh iface-XX |
| virsh-network.c | networkCmds | virsh net-XX |
| virsh-nodedev.c | nodedevCmds | virsh net-XX |
| virsh-nwfilter.c | nwfilterCmds | virsh nwfilter-XX |
| virsh-pool.c | storagePoolCmds | virsh pool-XX |
| virsh-secret.c | secretCmds | virsh secret-XX |
| virsh-snapshot.c | snapshotCmds | virsh snapshot-XX |
| virsh-volume.c | storageVolCmds | virsh vol-XX |
有了上面的表格我们就能够根据使用的virsh命令找到对应文件的对应vshCmdDef变量
/*
* vshCmdDef - command definition
*/
struct _vshCmdDef {
const char *name; /* name of command, or NULL for list end */
bool (*handler) (vshControl *, const vshCmd *); /* command handler */
const vshCmdOptDef *opts; /* definition of command options */
const vshCmdInfo *info; /* details about command */
unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */
};
一个vshCmdDef结构对应一个virsh命令,其中vshCmdOptDef定义了命令的参数,vshCmdInfo定义了命令的帮助信息,bool (*handler) (vshControl *, const vshCmd *)定义了命令的处理函数。
实际应用
如何阅读virsh start处理代码
- 查看virsh-domain.c文件的domManagementCmds变量,找到
{.name = "start",
.handler = cmdStart,
.opts = opts_start,
.info = info_start,
.flags = 0
}
- 查看opts_start了解命令参数
static const vshCmdOptDef opts_start[] = {
VIRSH_COMMON_OPT_DOMAIN(N_("name of the inactive domain")),
#ifndef WIN32
{.name = "console",
.type = VSH_OT_BOOL,
.help = N_("attach to console after creation")
},
#endif
{.name = "paused",
.type = VSH_OT_BOOL,
.help = N_("leave the guest paused after creation")
},
{.name = "autodestroy",
.type = VSH_OT_BOOL,
.help = N_("automatically destroy the guest when virsh disconnects")
},
{.name = "bypass-cache",
.type = VSH_OT_BOOL,
.help = N_("avoid file system cache when loading")
},
{.name = "force-boot",
.type = VSH_OT_BOOL,
.help = N_("force fresh boot by discarding any managed save")
},
{.name = "pass-fds",
.type = VSH_OT_STRING,
.help = N_("pass file descriptors N,M,... to the guest")
},
{.name = NULL}
};
- 查看cmdStart了解命令处理代码,即对应libvirt api的调用方法,此处是对
virDomainCreateWithFiles或virDomainCreate的调用
static bool cmdStart(vshControl *ctl, const vshCmd *cmd)
libvirt代码阅读
理解libvirt的代码架构就需要理解三个接口,libvirt通过高度抽象的接口对上层应用提供统一的入口,屏蔽底层的具体实现
| 接口 | 说明 | 代码目录 |
|---|---|---|
| virHypervisorDriver | 虚拟机管理接口 | qemu目录(qemu-kvm虚拟化)、xen目录(xen虚拟化)、lxc目录(lxc虚拟化)、vmware目录(vmware虚拟化) |
| virStorageDriver | 磁盘管理接口 | storage目录 |
| virNetworkDriver | 网络管理接口 | network目录 |
qemu-kvm虚拟化实现
首先我们进入qemu目录来看qemu_driver.c中的静态变量qemuHypervisorDriver,它就是virHypervisorDriver接口的qemu-kvm实现,例如通过查询这个变量,我们就知道libvirt api的domainListAllSnapshots的qemu-kvm实现就是qemuDomainListAllSnapshots函数
static virHypervisorDriver qemuHypervisorDriver = {
****省略****
.domainListAllSnapshots = qemuDomainListAllSnapshots, /* 0.9.13 */
****省略****
}
实际应用
虚拟机启动,libvirt磁盘的backing_chain形成过程
- 通过
virsh start命令我们知道虚拟机启动调用的api为domainCreateWithFlags,然后我们知道对应的实现为qemuDomainCreateWithFlags - 分析
qemuDomainCreateWithFlags函数
qemuDomainObjStart()
{
qemuProcessStart()
{
qemuProcessPrepareDomain()
{
qemuDomainCheckDiskPresence()
{
// 磁盘的backing_chain形成逻辑
qemuDomainDetermineDiskChain()
}
}
}
}
分析
qemuDomainDetermineDiskChain我们了解到virStorageFileGetMetadataRecurse就是正真实现磁盘backing_chain的函数,这边相当于libvirt执行了qemu-img info命令我们再看点更底层的东西,例如在backing_chain形成中是如何读取磁盘的backing信息,即
virStorageFileGetMetadataInternal函数实现细节
virStorageFileGetMetadataInternal
{
//读取backing信息,fileTypeInfo是util/virstoragefile.c中的静态变量,该变量定义了各种格式文件的backing信息读取方法
fileTypeInfo[meta->format].getBackingStore()
}
static struct FileTypeInfo const fileTypeInfo[] = {
****省略****
[VIR_STORAGE_FILE_QCOW2] = {
0, "QFI", NULL,
LV_BIG_ENDIAN, 4, 4, {2, 3},
QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore,
qcow2GetFeatures
},
****省略****
}
- 仔细分析
qcow2GetBackingStore函数可以知道backing_format信息在标准header信息之外,这就是qemu-img create -f qcow2 -b生成的backing_chain会有问题,而qemu-img create -f qcow2 -o不会的原因
Libvirt代码架构的更多相关文章
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP ...
- 图说socket与系统调用代码架构
1.引言 正式开始之前,每个人心里都应该有一点逼数,就像下面这张图一样. 系统调用也是函数调用,系统函数也是函数代码.系统函数与普通函数唯一的不同在于,系统函数可以使用cpu体系结构指令集中的特权指令 ...
- 代码架构.md
代码架构 待办 昨天待办 decription decription 我的流程逻辑(异常处理方式) 1568097677501.drawio.html 29.94 KB 异常的两种处理方式 异常的两种 ...
- 巡风代码架构简介以及Flask的项目文件结构简介
一.巡风: 巡风是一款什么东西,想必安全同行都不陌生吧.用它作为内网漏洞扫描管理架构是一种很好的选择,扫描快,开源,还可自己编写符合规则的POC直接放入相应目录来扩展.今天下午趁着有点时间捋了一下巡风 ...
- (转)App工程结构搭建:几种常见Android代码架构分析
关于Android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角度,看到整齐的代码,优美的分层总是一种舒服的享受的. 从艺术的角度看,其实我们是在追求一种美. 本文先分析几个当 ...
- 48、android代码架构总结
之前是按功能模块进行分类,现在随着功能模块越来越多,代码层次不再清晰,所以修改了工程结构: 之前: 经过修改现在: 1.更严谨的遵循mvc架构 bean目录存放的是数据模型 ui存储的是activit ...
- Asterisk 代码架构概述
from:http://blog.csdn.net/yetyongjin/article/details/7594447 近日分析Asterisk 1.8源码.Asterisk trunk上有这篇架构 ...
- gRPC Java的代码架构
RPC(远程过程调用) 的架构最常见的是"动态代理"方式,事先定义好接口,用一个代理假装实现了这个接口(真正的实现放在服务端),供客户端调用,代理内部将该方法调用封装成一个网络请求 ...
- LInux基础(04)项目设计一(理解链表管理协议的代码架构)
要设计好一个项目必须要有一个健全的代码框架 一个结构体内有数据域和处理数据的函数指针, 先实现管理链表的函数 增加节点 删除节点 清空链表 遍历节点对每个节点进行操作 再实现协议的注册 把对象s ...
随机推荐
- matlab画圆
MATLAB rectangle函数1 语法说明rectangle('Position', pos)rectangle('Position', pos, 'Curvature', cur)rectan ...
- POJ 2728 Desert King:最优比率生成树
题目链接:http://poj.org/problem?id=2728 题意: 给你n个点(x,y,z),让你求一棵生成树,使得 k = ∑ |z[i]-z[j]| / ∑ dis(i,j)最小. | ...
- javascript中的this值
如何确定this的值 this值会被传递给所有函数,this的值是基于运行时调用函数的上下文. 例如:从全局作用域调用sayFoo函数时,this引用window对象, 当它作为myObject的一 ...
- 一张图理解is_nll isset empty
isset 判断变量是否已存在,如果变量存在则返回 TRUE,否则返回 FALSE. empty 判断变量是否为空,如果变量是非空 或非零 的值,则 empty() 返回 FALSE.换句话说,&qu ...
- ibatis的resultClass与resultMap 的区别
ibatis的resultClass与resultMap还是有很大的区别.以下是我碰到的一个问题. 配置文件写法如下: 1 sqlMap2 typeAlias alias="notice&q ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- phpStudy如何修改端口及WWW目录
phpStudy如何修改端口及WWW目录 phpStudy如何修改端口 请使用『其他选项菜单』-『phpStudy设置』-『端口常规设置』.
- Python习题-统计日志中访问次数超过限制的IP
#1.1分钟之内ip访问次数超过200次的,就给他的ip加入黑名单#需求分析: #1.读日志,1分钟读一次 #2.获取这1分钟之内所有访问的ip #3.判断ip出现的次数,如果出现200次,那么就加入 ...
- Spring源码分析_01_ idea搭建spring源码阅读环境
二.参考资料 1.Intellij Idea如何导入spring源码
- django学习笔记(二)模板
1.当模板中的变量名遇到点时,以下面的顺序查找(短路逻辑): (1)字典类型查找: >>> from django.template import Template, Context ...