本指南介绍如何使用 metadata 库中)。元数据是任意数据 由驱动程序创建的 驱动程序绑定到其子节点通常,驱动程序可以创建自己的 FIDL 协议来传递元数据,但是, metadata 库提供了用于传递 以更少的代码实现驱动程序之间的元数据转换。
您可以找到司机发送、检索和转发元数据的示例 此处。
元数据定义
首先,元数据的类型必须定义为 FIDL 类型:
library fuchsia.examples.metadata;
// Type of the metadata to be passed.
type Metadata = table {
1: test_property string:MAX;
};
系统将使用
fuchsia.driver.metadata/Service
FIDL 服务。但是,传出命名空间中的服务名称
将不会是 fuchsia.driver.metadata.Service
。相反,它是一个自定义
我们要提供的字符串,该字符串与元数据的类型相关联。
在本教程中,我们将在上述同一 FIDL 库中定义该字符串:
library fuchsia.examples.metadata;
const SERVICE string = "fuchsia.examples.metadata.Metadata";
FIDL 库的 build 目标定义如下:
fidl("fuchsia.examples.metadata") {
sources = [ "fuchsia.examples.metadata.fidl" ]
}
元数据库
为了使用 metadata 库中,我们需要专门指定 fdf_metadata::ObjectDetails 模板 类:
#include <fidl/fuchsia.examples.metadata/cpp/fidl.h>
// `ObjectDetails` must be specialized within the `fdf_metadata` namespace.
namespace fdf_metadata {
template <>
// Pass the metadata type as the template argument.
struct ObjectDetails<fuchsia_examples_metadata::Metadata> {
// Specify the name of the service used to serve the metadata.
inline static const char* Name = fuchsia_examples_metadata::kService;
};
} // namespace fdf_metadata
由于发送和接收驱动程序都需要执行此操作,因此我们可以 添加到两个驱动程序都将包含的新库中:
source_set("examples_metadata") {
# This header file should contain the above code.
sources = [ "examples_metadata.h" ]
public_deps = [
# This should be the fuchsia.examples.metadata FIDL library's C++ target.
":fuchsia.examples.metadata_cpp",
]
}
发送元数据
初始设置
假设我们有一个要向其子项发送元数据的驱动程序:
#include <lib/driver/component/cpp/driver_export.h>
class Sender : public fdf::DriverBase {
public:
Sender(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: DriverBase("parent", std::move(start_args), std::move(driver_dispatcher)) {}
};
FUCHSIA_DRIVER_EXPORT(Sender);
其组件清单如下所示: ``` { 包括:[ "inspect/client.shard.cml", "syslog/client.shard.cml", ], program: { runner:“driver”, 二进制文件:“driver/parent.so” bind: "meta/bind/parent.bindbc", }, }
It's build targets are defined as follows:
fuchsia_driver("driver") { testonly = true output_name = "parent" 来源 = [ "parent.cc", ] deps = [ "//src/devices/lib/driver:driver_runtime", ] }
fuchsia_driver_component("component") { testonly = true component_name = "parent" manifest =“meta/parent.cml” deps = [ ":driver", ":bind", # 本教程中未指定的绑定规则。 ] info = "parent.json"# 本教程中未指定的信息。 } ```
发送流程
为了让此驱动程序将元数据发送给其子驱动程序,需要
的
fdf_metadata::MetadataServer
类,通过调用其
fdf_metadata::MetadataServer::SetMetadata()
方法,然后使用
发送到驱动程序的外发目录中
fdf_metadata::MetadataServer::Serve()
方法:
// Make sure to include the metadata library that specializes the
// `fdf_metadata::ObjectDetails` class. It is needed by
// `fdf_metadata::MetadataServer`.
#include "examples_metadata.h"
#include <lib/driver/metadata/cpp/metadata_server.h>
class Sender : public fdf::DriverBase {
public:
zx::result<> Start() override {
// Set the metadata to be served.
fuchsia_examples_metadata::Metadata metadata{{.test_property = "test value"}};
ZX_ASSERT(metadata_server_.SetMetadata(std::move(metadata)) == ZX_OK);
// Serve the metadata to the driver's outgoing directory.
ZX_ASSERT(metadata_server_.Serve(*outgoing(), dispatcher()) == ZX_OK);
return zx::ok();
}
private:
// Responsible for serving metadata.
fdf_metadata::MetadataServer<fuchsia_examples_metadata::Metadata> metadata_server_;
};
可以多次调用 fdf_metadata::MetadataServer::SetMetadata()
,
在 fdf_metadata::MetadataServer::Serve()
之前或之后,以及元数据服务器
将提供最新的元数据实例。驱动程序将无法检索
元数据(如果未调用 fdf_metadata::MetadataServer::SetMetadata()
)
然后再尝试检索元数据。
driver
构建目标需要更新:
fuchsia_driver("driver") {
testonly = true
output_name = "parent"
sources = [
"parent.cc",
]
deps = [
"//src/devices/lib/driver:driver_runtime",
":examples_metadata",
]
}
公开元数据服务
最后,驱动程序需要声明和公开
fuchsia.examples.metadata.Metadata
FIDL 服务在其组件清单中:
{
include: [
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/parent.so",
bind: "meta/bind/parent.bindbc",
},
capabilities: [
{ service: "fuchsia.examples.metadata.Metadata" },
],
expose: [
{
service: "fuchsia.examples.metadata.Metadata",
from: "self",
},
],
}
从技术上讲,不存在 fuchsia.examples.metadata.Metadata
FIDL 服务。
在后台,
fdf_metadata::MetadataServer
提供
fuchsia.driver.metadata/Service
FIDL 服务才能发送元数据。不过,
fdf_metadata::MetadataServer
不以“fuchsia.driver.metadata.Service
”名称提供此服务
像普通 FIDL 服务一样。而是以
fuchsia.examples.metadata.Metadata
。这样,接收方驱动程序就可以
指明正在传递的元数据类型。也就是说,我们需要声明
并公开 fuchsia.examples.metadata.Metadata
服务
不存在。
检索元数据
初始设置
假设我们的驱动程序希望从其父级接收元数据 驱动程序:
#include <lib/driver/component/cpp/driver_export.h>
class Retriever : public fdf::DriverBase {
public:
Retriever(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: DriverBase("child", std::move(start_args), std::move(driver_dispatcher)) {}
};
FUCHSIA_DRIVER_EXPORT(Retriever);
其组件清单如下所示:
{
include: [
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/child.so",
bind: "meta/bind/child.bindbc",
},
}
其构建目标的定义如下:
fuchsia_driver("driver") {
testonly = true
output_name = "child"
sources = [
"child.cc",
]
deps = [
"//src/devices/lib/driver:driver_runtime",
]
}
fuchsia_driver_component("component") {
testonly = true
component_name = "child"
manifest = "meta/child.cml"
deps = [
":driver",
":bind", # Bind rules not specified in this tutorial.
]
info = "child.json" # Info not specified in this tutorial.
}
检索过程
为了从驱动程序的父驱动程序中检索元数据,驱动程序需要
调用 fdf_metadata::GetMetadata()
:
#include <lib/driver/metadata/cpp/metadata.h>
// Make sure to include the metadata library that specializes the
// `fdf_metadata::ObjectDetails` class. It is needed by
// `fdf_metadata::GetMetadata()`.
#include "examples_metadata.h"
class Retriever : public fdf::DriverBase {
public:
zx::result<> Start() override {
zx::result<fuchsia_examples_metadata::Metadata> metadata =
fdf_metadata::GetMetadata<fuchsia_examples_metadata::Metadata>(incoming());
ZX_ASSERT(!metadata.is_error());
return zx::ok();
}
};
driver
构建目标需要更新:
fuchsia_driver("driver") {
testonly = true
output_name = "child"
sources = [
"child.cc",
]
deps = [
"//src/devices/lib/driver:driver_runtime",
":examples_metadata",
]
}
使用元数据服务
最后,驱动程序需要声明对
fuchsia.examples.metadata.Metadata
FIDL 服务在其组件清单中:
{
include: [
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/child.so",
bind: "meta/bind/child.bindbc",
},
use: [
{ service: "fuchsia.examples.metadata.Metadata" },
],
}
转发元数据
初始设置
假设我们有一个驱动程序希望从其父级检索元数据 驱动程序,并将该元数据转发给其子驱动程序:
#include <lib/driver/component/cpp/driver_export.h>
class Forwarder : public fdf::DriverBase {
public:
Forwarder(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: DriverBase("forward", std::move(start_args), std::move(driver_dispatcher)) {}
};
FUCHSIA_DRIVER_EXPORT(Forwarder);
其组件清单如下所示:
{
include: [
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/forward_driver.so",
bind: "meta/bind/forward.bindbc",
},
}
其构建目标的定义如下:
fuchsia_driver("driver") {
testonly = true
output_name = "forward_driver"
sources = [
"forward_driver.cc",
]
deps = [
"//src/devices/lib/driver:driver_runtime",
]
}
fuchsia_driver_component("component") {
testonly = true
component_name = "forward"
manifest = "meta/forward.cml"
deps = [
":driver",
":bind", # Bind rules not specified in this tutorial.
]
info = "forward.json" # Info not specified in this tutorial.
}
转发流程
为了让驱动程序将元数据从父驱动程序转发给子驱动程序
它需要一个
fdf_metadata::MetadataServer
类,通过调用其
fdf_metadata::MetadataServer::ForwardMetadata()
方法,然后使用
发送到驱动程序的外发目录中
fdf_metadata::MetadataServer::Serve()
方法:
// Make sure to include the metadata library that specializes the
// `fdf_metadata::ObjectDetails` class. It is needed by
// `fdf_metadata::MetadataServer`.
#include "examples_metadata.h"
#include <lib/driver/metadata/cpp/metadata_server.h>
class Forwarder : public fdf::DriverBase {
public:
zx::result<> Start() override {
// Set metadata using the driver's parent driver metadata.
ZX_ASSERT(metadata_server_.ForwardMetadata(incoming()) == ZX_OK);
// Serve the metadata to the driver's outgoing directory.
ZX_ASSERT(metadata_server_.Serve(*outgoing(), dispatcher()) == ZX_OK);
return zx::ok();
}
private:
// Responsible for serving metadata.
fdf_metadata::MetadataServer<fuchsia_examples_metadata::Metadata> metadata_server_;
};
请注意,fdf_metadata::MetadataServer::ForwardMetadata()
不检查父级驱动程序在之后是否更改了它提供的元数据
已调用 fdf_metadata::MetadataServer::ForwardMetadata()
。驾驶员
必须在以下时间后再次调用fdf_metadata::MetadataServer::ForwardMetadata()
:
以便应用相应更改
driver
构建目标需要更新:
fuchsia_driver("driver") {
testonly = true
output_name = "forward_driver"
sources = [
"forward_driver.cc",
]
deps = [
"//src/devices/lib/driver:driver_runtime",
":examples_metadata",
]
}
公开并使用元数据服务
最后,驱动程序需要声明、使用和公开
fuchsia.examples.metadata.Metadata
FIDL 服务在其组件清单中:
{
include: [
"inspect/client.shard.cml",
"syslog/client.shard.cml",
],
program: {
runner: "driver",
binary: "driver/forward_driver.so",
bind: "meta/bind/forward.bindbc",
},
capabilities: [
{ service: "fuchsia.examples.metadata.Metadata" },
],
expose: [
{
service: "fuchsia.examples.metadata.Metadata",
from: "self",
},
],
use: [
{ service: "fuchsia.examples.metadata.Metadata" },
],
}