zx_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,並將訊息的一部分取代為讀取自使用者空間的訊息。核心產生的 txid 將介於 0x80000000 到 0xFFFFFFFF 之間,而且與這個管道端點的任何其他 zx_channel_call() 進行中,不會與任何 txid 衝突。如果寫入訊息的長度少於四位元組,就會回報錯誤。

寫入傳出訊息時,系統會同時註冊興趣與相符 txid 的傳入訊息。

期限可根據工作的計時器處理政策自動調整。

雖然不會傳遞經過 slack 調整的「deadline」,但如果傳入訊息抵達具有相符的 txid,而是直接傳遞至一般傳入訊息佇列的尾端,它會直接傳送至在 zx_channel_call() 中等待的執行緒。

如果這類回覆在經過 slack 調整的Deadline 後送達,則會抵達一般傳入訊息佇列,導致 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;

wr_bytes 陣列最多只能有 ZX_CHANNEL_MAX_MSG_IOVEC8192 zx_channel_iovec_t 個元素,所有 zx_channel_iovec_t 中的 capacity 總和不會超過 ZX_CHANNEL_MAX_MSG_BYTES65536 位元組。buffer 不必對齊,且只有在 capacity 為零時,可能為 NULLreserved 必須設為 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_bytesactual_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_byteswr_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_bytesrd_num_handles 太小,因此無法包含回覆訊息。

ZX_ERR_NOT_SUPPORTED 帳號代碼中的其中一個控點是「控制代碼」 (指向寫入管道的控制代碼)。

附註

zx_channel_call() 提供的設施可直接使用 zx_channel_read()zx_channel_write() 與訊息調度工具互通,前提是必須觀察下列規則:

  1. 透過 zx_channel_read() 接收同步訊息的伺服器應確保收到的訊息會透過 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())。這個系統呼叫的設計宗旨是預期逾時通常會嚴重錯誤,用戶端不會預期在已逾時的管道上繼續進行通訊。

另請參閱