总结
向频道发送消息并等待回复。
声明
#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 bytes 用于将回复消息与发送消息进行匹配,使多个调用线程能够共享一个频道,而无需进行任何其他用户空间记录。
此操作的写入和读取阶段的行为类似于 zx_channel_write()
和 zx_channel_read()
,区别在于其参数是通过 zx_channel_call_args_t
结构提供的。
系统会将写入和回读消息的前四个字节视为 zx_txid_t
类型的事务 ID。内核会为写入的消息生成 txid,并将消息中的这一部分替换为从用户空间读取的。
内核生成的 txid 将介于 0x80000000 和 0xFFFFFFFF 之间,并且不会与任何正在针对此通道端点进行的 zx_channel_call()
中的任何 txid 发生冲突。如果写入的消息长度少于 4 个字节,则报告错误。
写入出站消息时,系统会同时为匹配的 txid 的入站消息注册兴趣。
deadline 可能会根据作业的计时器延迟政策自动调整。
虽然尚未超过针对 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;
wr_bytes
数组中最多只能有 ZX_CHANNEL_MAX_MSG_IOVEC
或 8192
个 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_handles 都必须具有 ZX_RIGHT_TRANSFER
。
返回值
zx_channel_call()
会在成功时返回 ZX_OK
,回复消息中的字节数和句柄数分别通过 actual_bytes 和 actual_handles 返回。
错误
ZX_ERR_BAD_HANDLE
handle 不是有效的句柄,handles 中的任何元素都不是有效的句柄,或者 handles 数组中的句柄存在重复。
ZX_ERR_WRONG_TYPE
标识名不是频道标识名。
ZX_ERR_INVALID_ARGS
提供的任何指针无效或 null,或 wr_num_bytes 小于 4,或者 options 为非零值。如果指定了 ZX_CHANNEL_WRITE_USE_IOVEC
选项,则当 buffer 字段包含无效指针或预留字段为非零时,将会生成 ZX_ERR_INVALID_ARGS
。
ZX_ERR_ACCESS_DENIED
handle 没有 ZX_RIGHT_WRITE
,或 handles 中的任何元素都没有 ZX_RIGHT_TRANSFER
。
ZX_ERR_PEER_CLOSED
通道的另一端在等待回复时已关闭或关闭。
等待回复时,ZX_ERR_CANCELED
标识名已失效(例如已关闭)。
ZX_ERR_NO_MEMORY
由于内存不足而失败。
用户空间没有什么方法来处理此(不太可能)错误。在以后的 build 中,此错误不会再发生。
ZX_ERR_OUT_OF_RANGE
wr_num_bytes 或 wr_num_handles 大于通道消息允许的大小上限。如果指定了 ZX_CHANNEL_WRITE_USE_IOVEC
选项,则当 num_bytes 大于 ZX_CHANNEL_MAX_MSG_IOVEC
或 iovec 容量之和超过 ZX_CHANNEL_MAX_MSG_BYTES
时,会生成 ZX_ERR_OUT_OF_RANGE
。num_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()
接收同步消息的服务器应通过zx_channel_write()
确保传入消息的 xid 反映在传出响应中,以便使用zx_channel_call()
的客户端可以正确路由回复。通过
zx_channel_write()
发送消息的客户端应确保只使用 0x7FFFFFFF 之间的 txid,以避免与通过zx_channel_call()
通信的其他线程发生冲突。
如果 zx_channel_call()
因 ZX_ERR_TIMED_OUT
而返回,且服务器最终在将来的某个时间点进行回复,则该回复可以与其他出站请求匹配(前提是自原始请求以来发生了大约 2^31 个 zx_channel_call()
)。此系统调用围绕以下预期设计:超时通常很严重,客户端不会希望在超时的通道上继续通信。
另请参阅
- 计时器 Slack
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()