摘要
向频道发送消息并等待回复。
声明
#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_bytes 和 rd_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_IOVEC
或 8192
wr_bytes
数组的 zx_channel_iovec_t
个元素,其总和为
所有zx_channel_iovec_t
中的capacity
不超过
ZX_CHANNEL_MAX_MSG_BYTES
或 65536
字节。buffer
无需对齐,
仅当 capacity
为零时,才能为 NULL
。reserved
必须设置为零。
要么全部复制 zx_channel_iovec_t
,要么不发送消息
且邮件不会被发送。用于发送标识名的用法不变。
权限
handle 的类型必须为 ZX_OBJ_TYPE_CHANNEL
,包含 ZX_RIGHT_READ
且 ZX_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_bytes 或 wr_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_bytes 或 rd_num_handles 位数过小
以包含回复消息。
ZX_ERR_NOT_SUPPORTED
handles 中的一个句柄是 handle
(正在写入的通道的句柄)。
备注
zx_channel_call()
提供的工具可与消息调度程序进行互操作
直接使用 zx_channel_read()
和 zx_channel_write()
,前提是以下规则
可观察到:
通过
zx_channel_read()
接收同步消息的服务器应确保 收到消息的 txid 会通过zx_channel_write()
反映在外发响应中 以便使用zx_channel_call()
的客户端可以正确路由回复。如果客户端通过
zx_channel_write()
发送将回复的消息,则应确保 它仅使用 0 到 0x7FFFFFFF 之间的 txid,以避免与其他线程发生冲突 通过zx_channel_call()
进行通信。
如果 zx_channel_call()
因 ZX_ERR_TIMED_OUT
而返回,如果服务器最终回复,
在未来某个时间点,回复可能与另一个出站请求匹配(如果
自原始请求以来发生了 2^31 次 zx_channel_call()
。此系统调用旨在
预计超时通常是严重的,并且客户预计不会继续
在超时频道上的通信。
另请参阅
- 计时器空闲时间
zx_channel_create()
zx_channel_read()
zx_channel_write()
zx_handle_close()
zx_handle_replace()
zx_object_wait_async()
zx_object_wait_many()
zx_object_wait_one()