QEMU 新增QMP&HMP指令【原文阅读】

0x0 QEMU原文

https://www.qemu.org/docs/master/devel/writing-monitor-commands.html

0x1

0x11 How to write monitor commands

本文档是关于如何使用QAPI框架和HMP命令编写新的QMP命令的分步指南。
本文不讨论QMP协议级别的细节,也不深入讨论QAPI框架的实现。
有关QAPI框架的深入介绍,请参考
关于QMP协议,请参考

新命令只能在QMP中实现。新的HMP命令应该在QMP的基础上实现。
典型的HMP命令包装在等效的QMP命令周围,但从QMP构建块构建的HMP方便命令也很好。
长期目标是使所有现有的HMP命令都符合此要求,以便将HMP与QEMU的内部完全隔离。
请参阅编写返回非结构化文本的调试辅助工具一节,了解有关传统上仅为HMP的命令的进一步指导。

0x12 Overview

一般来说,为了编写一个新的QMP命令,应该采取以下步骤:
1、在适当的QAPI模式模块中定义命令和它需要的任何类型。
2、编写QMP命令本身,这是一个常规的C函数。最好,该命令应该由某个QEMU子系统导出。但也可以将其添加到monitor/qmp-cmds.c文件中
3、此时可以在QMP协议下测试命令。
4、这不是必需的,只有当在HMP中具有该功能确实有意义时,才应该这样做。

HMP命令是通过QMP命令来实现的,下面的部分将演示上面的每个步骤。我们将从非常简单的开始,并随着我们的进展而变得更加复杂。

0x13 Testing

对于下一节中的所有示例,测试设置都是相同的,如下所示。
首先,QEMU应该像这样启动:

# qemu-system-TARGET [...] \
    -chardev socket,id=qmp,port=4444,host=localhost,server=on \
    -mon chardev=qmp,mode=control,pretty=on

然后,在另一个终端中:

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{
    "QMP": {
        "version": {
            "qemu": {
                "micro": 50,
                "minor": 2,
                "major": 8
            },
            "package": ...
        },
        "capabilities": [
            "oob"
        ]
    }
}

上面的输出是QMP服务器说你已经连接了。服务器实际上处于能力协商模式。要进入命令模式,请键入:

{ "execute": "qmp_capabilities" }

则服务器应响应:

{
    "return": {
    }
}

这就是QMP的说法“最新的命令执行正常,没有返回任何数据”。现在,您可以输入QMP示例命令,如下文所述。

0x2

0x21 Writing a simple command: hello-world

这就是可以编写的最简单的QMP命令。
通常,此类命令在QEMU中携带一些有意义的操作,但在这里,它只是将“Hello,world”打印到标准输出。

我们的命令将被称为“hello-world”。它不接受任何参数,也不返回任何数据。

第一步是在适当的QAPI模式模块中定义命令。我们选择模块qapi/misc.json,并在底部添加以下行:

##
# @hello-world:
#
# Since: 9.0
##
{ 'command': 'hello-world' }

“command”关键字定义新的QMP命令。它指示QAPI生成任何原型和必要的代码来封送和拆封协议数据

下一步是编写“hello-world”实现。如前所述,命令最好位于QEMU子系统中。
但是“hello-world”并不涉及任何,因此我们将其实现放在monitor/qmp-cmds.c中:

void qmp_hello_world(Error **errp)
{
    printf("Hello, world!\n");
}

QMP命令实现函数必须以“qmp_”为前缀
qmp_hello_world()返回void,这与该命令不返回任何数据的事实相符,
它采用“Error**”参数。这是必需的。稍后,我们将看到如何返回错误并接受额外的参数。如果命令没有返回错误,则不应使用Error参数
我们不会添加函数的原型。这是由QAPI自动完成的。
不建议使用QMP命令打印到终端,我们在这里这样做,因为这是演示QMP命令最简单的方法

你完了。现在构建QEMU,按照“测试”一节中的建议运行它,然后键入以下QMP命令:

{ "execute": "hello-world" }

然后检查运行QEMU的终端,查找“Hello,world”字符串。如果你没有看到它,那么就出了问题。

0x22 Arguments

0x3

0x31 Implementing the HMP command

让我们向“hello-world”命令添加参数。
我们要做的第一个更改是将模式文件中的命令规范修改为:

##
# @hello-world:
#
# @message: message to be printed (default: "Hello, world!")
#
# @times: how many times to print the message (default: 1)
#
# Since: 9.0
##
{ 'command': 'hello-world',
  'data': { '*message': 'str', '*times': 'int' } }

注意模式中的新’data’成员。它指定一个QAPI类型’str’的参数’message’和一个QAPI类型’int’的参数’times’。另请注意星号,它用于标记参数可选。
现在,让我们在monitor/qmp-cmds.c中更新我们的C实现:

void qmp_hello_world(const char *message, bool has_times, int64_t times,
                     Error **errp)
{
    if (!message) {
        message = "Hello, world";
    }
    if (!has_times) {
        times = 1;
    }

    for (int i = 0; i < times; i++) {
        printf("%s\n", message);
    }
}

有两个重要的细节需要注意:

除了指针之外的可选参数都伴随着一个’has_'布尔值,如果可选参数存在,则设置该布尔值,否则设置该布尔值。
C实现签名必须遵循模式的参数顺序,该顺序由“data”成员定义,以测试我们的新版本的“hello-world”命令。

构建QEMU,按照“测试”部分所述运行它,然后发送两个命令:

{ "execute": "hello-world" }
{
    "return": {
    }
}

{ "execute": "hello-world", "arguments": { "message": "We love QEMU" } }
{
    "return": {
    }
}

您应该在运行QEMU的终端中看到“Hello,world”和“We love QEMU”,如果您没有看到这些字符串,那么就出问题了

0x4

0x41 Writing more complex commands

0x42 Modelling data in QAPI

0x43 User Defined Types

0x44 The HMP command

0x45 Writing a debugging aid returning unstructured text

0x46 Implementing the QMP command

0x47 Implementing the HMP command

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值