虚拟机配置中:

<channel type='unix'>

<target type='virtio' name='org.qemu.guest_agent.0'/>

<address type='virtio-serial' controller='0' bus='0' port='1'/>

</channel>

With qemu, if name is "org.qemu.guest_agent.0", then libvirt can interact with a guest agent installed in the guest, for actions such as guest shutdown or file system quiescing.

虚拟机启动命令行:

/usr/libexec/qemu-kvm

-chardev socket,id=charmonitor,fd=35,server,nowait

-mon chardev=charmonitor,id=monitor,mode=control

-chardev socket,id=charchannel0,fd=42,server,nowait

-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0

启动虚拟机时libvirt会创建一个qemu monitor的unix socket和一个qemu agent的unix socket:

srwxrwxr-x 1 root root 0 Jan 11 16:13 /var/lib/libvirt/qemu/domain-28-Centos7/monitor.sock

srwxrwxr-x 1 qemu qemu 0 Jan 11 16:13 /var/lib/libvirt/qemu/channel/target/domain-28-Centos7/org.qemu.guest_agent.0

qemu monitor和qemu agent通道创建过程

Libvirt-6.9

libvirt启动虚拟机时会打开两个unix socket,作为server,一个用作qemu monitor,一个用作qemu agent,然后启动qemu子进程。

qemuProcessStart

->qemuProcessPrepareDomain

->for循环执行qemuDomainPrepareChannel # 设置channel->source->data.nix.path,例如:/var/lib/libvirt/qemu/channel/target/domain-28-Centos7/org.qemu.guest_agent.0

qemuProcessLaunch

->qemuBuildCommandLine

->qemuBuildMonitorCommandLine

->qemuBuildChrChardevStr

->fd = qemuOpenChrChardevUNIXSocket # dev->type == VIR_DOMAIN_CHR_TYPE_UNIX

->virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT); # 将要传递的fd放在cmd->passfd中

->qemuBuildChannelsCommandLine

->qemuBuildChrChardevStr # VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO

->fd = qemuOpenChrChardevUNIXSocket(dev); # VIR_DOMAIN_CHR_TYPE_UNIX,打开unix socker listen

->virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);

->qemuBuildChrDeviceCommandLine # 生成-device参数

->virCommandRun # 启动qemu子进程,之后libvirt进程关闭cmd->passfd中的fd

->qemuProcessWaitForMonitor

->qemuConnectMonitor

->qemuMonitorOpen # 连接unix socket

->qemuProcessInitMonitor # 发送qmp_capabilities

->qemuMigrationCapsCheck # 发送query-migrate-capabilities

->qemuMonitorGetChardevInfo # 发送query-chardev

->qemuProcessRefreshChannelVirtioState # 增加domain agent生命周期事件

->qemuConnectAgent

->agent = qemuAgentOpen(...)

->agent->fd = qemuAgentOpenUnix(config->data.nix.path); # 通过unix socket连接到qemu agent,config->data.nix.path在之前的qemuDomainPrepareChannel 函数中已经设置好

->qemuAgentRegister(agent); # 使用glib事件循环监测qemu agent事件,处理函数为qemuAgentIO

qemu-5.0

qemu_init

->for循环执行chardev_init_func

->qemu_chr_new_from_opts

->backend = qemu_chr_parse_opts(opts, errp);

->qemu_chr_parse_socket # SOCKET_ADDRESS_LEGACY_KIND_FD

->chr = qemu_chardev_new(...)

->chardev_new

->qemu_char_open

->qmp_chardev_open_socket

->qmp_chardev_open_socket_server

qemu-5.0对qmp命令和qga命令的处理

全局变量qmp_dispatcher_bh用于进行qmp命令

/* Bottom half to dispatch the requests received from I/O thread */
QEMUBH *qmp_dispatcher_bh;

函数monitor_init_globals_core初始化qmp_dispatcher_bh并将其处理函数设置为monitor_qmp_bh_dispatcher

void monitor_init_globals_core(void)
{monitor_qapi_event_init();qemu_mutex_init(&monitor_lock);/** The dispatcher BH must run in the main loop thread, since we* have commands assuming that context.  It would be nice to get* rid of those assumptions.*/qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(),monitor_qmp_bh_dispatcher,NULL);
}

qmp命令的入口函数是qmp_dispatch:

virsh qemu-monitor-command --hmp info block调用堆栈如下:

Breakpoint 1, 0x000055fdab6f88a0 in hmp_info_block ()

(gdb) bt

#0  0x000055fdab6f88a0 in hmp_info_block ()

#1  0x000055fdab7e3dd6 in handle_hmp_command ()

#2  0x000055fdab674d12 in qmp_human_monitor_command ()

#3  0x000055fdab807019 in qmp_marshal_human_monitor_command ()

#4  0x000055fdab8c14b0 in qmp_dispatch ()

#5  0x000055fdab7e1111 in monitor_qmp_dispatch ()

#6  0x000055fdab7e17d0 in monitor_qmp_bh_dispatcher ()

#7  0x000055fdab9081e3 in aio_bh_poll ()

#8  0x000055fdab90b59e in aio_dispatch ()

#9  0x000055fdab90807e in aio_ctx_dispatch ()

#10 0x00007f25d5f15099 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0

#11 0x000055fdab90a8e3 in main_loop_wait ()

#12 0x000055fdab67b269 in qemu_main_loop ()

#13 0x000055fdab59c08e in main ()

virsh qemu-monitor-command '{"execute": "query-block"}'调用堆栈如下:

#0  0x000055fdab87b5a0 in qmp_query_block ()

#1  0x000055fdab7fc797 in qmp_marshal_query_block ()

#2  0x000055fdab8c1536 in qmp_dispatch ()

#3  0x000055fdab7e1111 in monitor_qmp_dispatch ()

#4  0x000055fdab7e17d0 in monitor_qmp_bh_dispatcher ()

#5  0x000055fdab9081e3 in aio_bh_poll ()

#6  0x000055fdab90b59e in aio_dispatch ()

#7  0x000055fdab90807e in aio_ctx_dispatch ()

#8  0x00007f25d5f15099 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0

#9  0x000055fdab90a8e3 in main_loop_wait ()

#10 0x000055fdab67b269 in qemu_main_loop ()

#11 0x000055fdab59c08e in main ()

qga命令的入口函数是tcp_chr_read:

tcp_chr_read

->qemu_chr_be_write

->chr_read # virtconsole_realize中调用qemu_chr_fe_set_handlers将backend的读函数设置为chr_read(virtio-console.c)

->virtio_serial_write

->virtqueue_push

->virtio_notify

之后就是通过virtio机制通知到虚拟机内部,虚拟机内部的qemu guest agent打开的virtio串口收到消息进行处理。

qemu monitor和qemu agent的实现相关推荐

  1. qemu monitor

    qemu向外界暴露的唯一接口就是 qemu monitor, 通过monitor可以 查询虚拟机信息, 控制虚拟机.传输数据方式是网络套结字. qemu monitor 支持几种协议类型: qmp 和 ...

  2. QEMU monitor控制台使用详解

    为什么要使用 QEMU monitor命令? 在前面学习ubuntu启动第一个虚拟机时,发现我们在使用启动QEMU之后,我们的终端会卡住.而现在我们在启动QEMU时使用了monitor,终端会进入mo ...

  3. QEMU多进程(Multi-process QEMU)及vfio-user应用

    1.Qemu现状-多线程锁竞争 2.Qemu现状-项目依赖太多 $ readelf -d /usr/bin/qemu-system-x86_64 | grep NEEDED | wc -l 60 $ ...

  4. 2022CTF培训(十三)虚拟化QEMU架构分析QEMU CVE示例分析

    附件下载链接 虚拟化技术基本概念 硬件虚拟化 全虚拟化 提供可以完全模拟基础硬件的VME 可以在VM中运行任何能够在物理硬件上执行的软件,并且可以在每个单独的VM中运行基础硬件支持的任何OS 为每个V ...

  5. linux下qemu共享文件夹,QEMU Windows来宾和Linux主机之间的共享文件夹

    QEMU的内置Samba服务 该-net user,smb选项不起作用是由于与较新的Samba版本(> = 4)不兼容而引起的.QEMU v2.2.0和更高版本中已通过以下更改修复了此问题: ( ...

  6. qemu里pci设备的热插拔

    qemu里pci设备的热插拔 -v0.1 2019.2.17 Sherlock Init -v0.2 2019.2.21 Sherlock Add all related command 本文讨论li ...

  7. virsh KVM管理工具

    virsh所有的命令 Domain Management (help keyword 'domain'):attach-device attach device from an XML fileatt ...

  8. 【虚拟化】virsh指令大全

    文章目录 1 - domain management 2 - Domain Monitoring 3 - Host and Hypervisor 4 - Checkpoint 5 - Interfac ...

  9. libvirt virsh domain命令解析(一)

    virsh是libvirt提供的命令行工具, 了解virsh命令的功能,可以快速了解libvirt的主要功能及功能特性 这里首先介绍domain domain 域, 可以看做是一个虚拟机实例 通过 v ...

最新文章

  1. python pip 换源
  2. php怎么删除多条,php 用checkbox一次性删除多条记录的方法
  3. 使用Git将我的最后一个X提交一起压缩
  4. mac 苹果多版本jdk自由切换
  5. 文件服务器和客户模式有什么区别,客户端和服务器端编程有什么区别?
  6. Mysql JDBC 连接串参数说明
  7. 地铁上怎么那么多钢管女郎?
  8. Spark源码分析之DiskBlockMangaer分析
  9. 解决tomcat在idea控制台乱码
  10. 计算机团队霸气名称大全,霸气吃鸡游戏团队名字大全
  11. HZOI20190903模拟36 字符,蛋糕,游戏
  12. 互联网周刊:深度分析云计算
  13. 如何给135编辑器推文添加附件
  14. 达达-京东到家完成新一轮5亿美金融资,沃尔玛、京东分别增持
  15. android根文件系统目录结构
  16. 解读人工智能的2021:回顾那些激动人心的重大突破
  17. msysgit - Windows Git安装配置
  18. 计算机动画主要学什么,动画专业主要学什么?
  19. ExecuteScaler的三种返回值
  20. 在线制作html邮件,HTML邮件设计注意点

热门文章

  1. QCD-品质、成本、交付
  2. 计算机app无法删除,电脑出现删除不了软件怎么处理?已经用了腾讯安全管家还是删不干净?...
  3. mendeley云端容量_除了Endnote,Mendeley也是你值得拥有的文献管理器
  4. 高等数学(第七版)同济大学 习题3-4 个人解答(后8题)
  5. 镜头C接口和CS接口的简单区分
  6. 愿自己余生不再焦虑慌张
  7. latex 排版笔记
  8. <Linux开发>驱动开发 -之-platform 驱动
  9. 线性代数笔记22——特征值和特征向量
  10. POC [Proof of Concept] 原型 / 概念证明