z_channel_call

摘要

向频道发送消息并等待回复。

声明

#include <zircon/syscalls.h>

zx_status_t zx_channel_call(zx_handle_t handle,
                            uint32_t options,
                            zx_time_t deadline,
                            const zx_channel_call_args_t* args,
                            uint32_t* actual_bytes,
                            uint32_t* actual_handles);

说明

zx_channel_call() 就像是 zx_channel_write()zx_object_wait_one()、 和 zx_channel_read(),还增加了一项功能,即交易 ID 为 消息载荷的前面 字节 用于匹配回复消息和发送 消息,使多个调用线程可以共享通道,而无需任何其他 用户空间簿记

此操作的写入和读取阶段的行为类似于 zx_channel_write()zx_channel_read() 不同的是,其参数是通过 zx_channel_call_args_t 结构。

系统会将读写消息的前四个字节 zx_txid_t 类型的交易 ID。内核会为 写入消息,将该部分消息替换为从用户空间读取的消息。 内核生成的 txid 将介于 0x80000000 到 0xFFFFFFFF 之间, 不与任何其他正在进行的 zx_channel_call() 的任何 TXID 冲突 这个频道端点如果撰写的消息的长度少于 4 个字符 字节,系统会报告错误。

出站消息写入后,系统会同时登记意向 匹配 txid 的入站邮件。

截止期限会根据作业的计时器时间延迟自动调整 政策。

当 Slack 调整后的截止日期还未过时,如果入站邮件 收到匹配的 txid,而不是添加到常规 消息队列,则会直接传递到等待 zx_channel_call()

如果此类回复在根据 Slack 调整的截止时间过去后收到, 进入常规入站消息队列,导致 ZX_CHANNEL_READABLE 有信号等

入站邮件太大,无法放入 rd_num_bytesrd_num_handles 份 在这种情况下,系统会舍弃它们,并返回 ZX_ERR_BUFFER_TOO_SMALL

zx_channel_write() 一样,句柄中的句柄始终会被 zx_channel_call() 且不再存在于调用进程中。

ZX_CHANNEL_WRITE_USE_IOVEC 选项

在指定 ZX_CHANNEL_WRITE_USE_IOVEC 选项后,wr_bytes 为 解释为 zx_channel_iovec_t 的数组,指定 按顺序复制到消息中。num_wr_bytes 用于指定 wr_bytes 中的 zx_channel_iovec_t 个数组元素。

typedef struct zx_channel_iovec {
  const void* buffer;      // User-space bytes.
  uint32_t capacity;       // Number of bytes.
  uint32_t reserved;       // Reserved.
} zx_channel_iovec_t;

最多只能有 ZX_CHANNEL_MAX_MSG_IOVEC8192 wr_bytes 数组的 zx_channel_iovec_t 个元素,其总和为 所有zx_channel_iovec_t中的capacity不超过 ZX_CHANNEL_MAX_MSG_BYTES65536 字节。buffer 无需对齐, 仅当 capacity 为零时,才能为 NULLreserved 必须设置为零。

要么全部复制 zx_channel_iovec_t,要么不发送消息 且邮件不会被发送。用于发送标识名的用法不变。

权限

handle 的类型必须为 ZX_OBJ_TYPE_CHANNEL,包含 ZX_RIGHT_READZX_RIGHT_WRITE

args 的所有 wr_handle 都必须具有 ZX_RIGHT_TRANSFER

返回值

zx_channel_call() 会在操作成功时返回 ZX_OK 以及字节数和 回复消息中的句柄计数通过 actual_bytes 返回, actual_handles

错误

ZX_ERR_BAD_HANDLE handle 不是有效的句柄,其中的任何元素 handles 不是有效的句柄,或者句柄存在重复 (位于 handles 数组中)。

ZX_ERR_WRONG_TYPE handle 不是频道句柄。

ZX_ERR_INVALID_ARGS 提供的指针中的任何一个无效或 null, 或 wr_num_bytes 小于 4,或 options 为非零值。 如果指定了 ZX_CHANNEL_WRITE_USE_IOVEC 选项, 如果 buffer 字段包含ZX_ERR_INVALID_ARGS 指针无效或预留字段为非零。

ZX_ERR_ACCESS_DENIED标识名不含 ZX_RIGHT_WRITE句柄中的任何元素都不包含 ZX_RIGHT_TRANSFER

ZX_ERR_PEER_CLOSED 频道的另一端已关闭或变为 已在等待回复时关闭。

ZX_ERR_CANCELED 句柄在等待回复时失效(例如,已关闭)。

ZX_ERR_NO_MEMORY 因内存不足而失败。 用户空间没有好办法处理这种(不太可能)错误。 在将来的版本中,此错误不会再发生。

ZX_ERR_OUT_OF_RANGE wr_num_byteswr_num_handles 大于 频道消息允许的最大大小。 如果指定了 ZX_CHANNEL_WRITE_USE_IOVEC 选项, ZX_ERR_OUT_OF_RANGE如果num_bytes超过 ZX_CHANNEL_MAX_MSG_IOVEC,或者 iovec 容量的总和超过 ZX_CHANNEL_MAX_MSG_BYTES

ZX_ERR_BUFFER_TOO_SMALL rd_num_bytesrd_num_handles 位数过小 以包含回复消息。

ZX_ERR_NOT_SUPPORTED handles 中的一个句柄是 handle (正在写入的通道的句柄)。

备注

zx_channel_call() 提供的工具可与消息调度程序进行互操作 直接使用 zx_channel_read()zx_channel_write(),前提是以下规则 可观察到:

  1. 通过 zx_channel_read() 接收同步消息的服务器应确保 收到消息的 txid 会通过 zx_channel_write() 反映在外发响应中 以便使用 zx_channel_call() 的客户端可以正确路由回复。

  2. 如果客户端通过 zx_channel_write() 发送将回复的消息,则应确保 它仅使用 0 到 0x7FFFFFFF 之间的 txid,以避免与其他线程发生冲突 通过 zx_channel_call() 进行通信。

如果 zx_channel_call()ZX_ERR_TIMED_OUT 而返回,如果服务器最终回复, 在未来某个时间点,回复可能与另一个出站请求匹配(如果 自原始请求以来发生了 2^31 次 zx_channel_call()。此系统调用旨在 预计超时通常是严重的,并且客户预计不会继续 在超时频道上的通信。

另请参阅