摘要
傳送訊息給管道並等待對方回覆。
宣告
#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,並將訊息的一部分取代為讀取自使用者空間的訊息。核心產生的 txid 將介於 0x80000000 到 0xFFFFFFFF 之間,而且與這個管道端點的任何其他 zx_channel_call()
進行中,不會與任何 txid 衝突。如果寫入訊息的長度少於四位元組,就會回報錯誤。
寫入傳出訊息時,系統會同時註冊興趣與相符 txid 的傳入訊息。
期限可根據工作的計時器處理政策自動調整。
雖然不會傳遞經過 slack 調整的「deadline」,但如果傳入訊息抵達具有相符的 txid,而是直接傳遞至一般傳入訊息佇列的尾端,它會直接傳送至在 zx_channel_call()
中等待的執行緒。
如果這類回覆在經過 slack 調整的Deadline 後送達,則會抵達一般傳入訊息佇列,導致 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
必須設為 0。
系統只會複製所有 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 陣列中的控點有重複。
ZX_ERR_WRONG_TYPE
帳號代碼不是管道帳號代碼。
ZX_ERR_INVALID_ARGS
提供的任何指標無效或空值,或 wr_num_bytes 小於四,或 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
選項,如果 num_bytes 大於 ZX_CHANNEL_MAX_MSG_IOVEC
,或生物容量總和超過 ZX_CHANNEL_MAX_MSG_BYTES
,就會產生 ZX_ERR_OUT_OF_RANGE
。
ZX_ERR_BUFFER_TOO_SMALL
rd_num_bytes 或 rd_num_handles 太小,因此無法包含回覆訊息。
ZX_ERR_NOT_SUPPORTED
帳號代碼中的其中一個控點是「控制代碼」 (指向寫入管道的控制代碼)。
附註
zx_channel_call()
提供的設施可直接使用 zx_channel_read()
和 zx_channel_write()
與訊息調度工具互通,前提是必須觀察下列規則:
透過
zx_channel_read()
接收同步訊息的伺服器應確保收到的訊息會透過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()