Skip to main content
内核 API 将 QRTR 端点建模为端口。客户端创建端口,在必要时解析服务,发送和接收消息,然后关闭端口。服务器还会额外注册和注销一个服务名称。

端口生命周期

端口经历以下阶段:
  1. 创建 —— 创建端口,并提供一个用于事件(有数据可读、写入完成、端口状态变化)通知的回调。
  2. 注册(可选) —— 如果该端口用于提供服务,注册服务名称以便客户端能够找到它。
  3. 就绪 —— 发送和接收消息,或查找远端服务。
  4. 注销(可选) —— 如果该端口曾注册为服务,在服务停止时注销它。
  5. 关闭 —— 关闭端口并清理资源。

内核空间接口

内核提供以下用于创建和管理端口的函数:
  • 创建端口 —— 提供一个在事件发生时(有数据可读、写入完成、端口状态变化)被调用的回调函数。回调会收到一个私有上下文指针,以便将端口与其所属的驱动状态关联。
  • 发送消息 —— 指定目的地(服务名称或端点地址)和要发送的数据。
  • 接收消息 —— 等待消息到达,可选带超时。接收函数返回载荷和源地址。
  • 注册服务 —— 将服务名称与该端口关联注册,供客户端查找。
  • 注销服务 —— 在服务停止时注销服务名称。
  • 关闭端口 —— 关闭端口并释放资源。

服务注册和查找

服务器将服务名称与其本地端口关联注册。当客户端拥有服务名称但没有当前端点地址时,会调用查找函数。返回的地址可能在服务重启或迁移时发生变化,因此客户端必须处理查找失败和地址过期错误。

用户空间 socket

用户空间应用通过面向消息的 socket 接口访问路由器。socket 生命周期遵循与内核 API 相同的模型:
  1. 创建 socket
  2. 绑定到本地地址或发现远端服务
  3. 发送和接收消息
  4. 关闭 socket
数据报边界被保留为消息边界,因此应用应按其期望接收的消息大小设置接收缓冲区大小。

API 参考

端口生命周期函数

以下函数管理 QRTR 端口的生命周期:
  • qrtr_endpoint_create(const char *xprt_name, uint32_t port_id, qrtr_rx_cb rx_cb, void *priv) —— 创建端口并注册一个回调,用于事件(有数据可读、写入完成、端口状态变化)的通知。
  • qrtr_sendto(uint32_t node_id, uint32_t port_id, const void *data, size_t len) —— 向由节点 ID 和端口 ID 指定的目的地发送消息。
  • qrtr_send_to_service(uint32_t service_id, uint32_t instance_id, const void *data, size_t len) —— 向由服务名称(服务 ID 和实例 ID)指定的目的地发送消息。
  • qrtr_recvfrom(uint32_t *node_id, uint32_t *port_id, void *data, size_t len, int timeout_ms) —— 等待消息到达,可选带超时。返回载荷和源地址。
  • qrtr_publish(uint32_t service_id, uint32_t instance_id, uint32_t version) —— 将服务名称与该端口关联注册,供客户端发现。
  • qrtr_unpublish(uint32_t service_id, uint32_t instance_id) —— 在服务停止时注销服务名称。
  • qrtr_endpoint_release(uint32_t port_id) —— 关闭端口并释放所有关联资源。

服务发现函数

  • qrtr_lookup_service(uint32_t service_id, uint32_t instance_id, uint32_t *node_id, uint32_t *port_id) —— 通过名称向路由器查询服务。返回该服务的端点地址(节点 ID 和端口 ID)。
  • qrtr_get_service_list(uint32_t service_id, struct qrtr_service_info *services, size_t num_services, size_t *num_returned) —— 获取与某个服务 ID 匹配的所有可用服务。

Socket 接口函数

用户空间应用使用标准的 socket 操作:
  • socket(AF_QIPCRTR, SOCK_DGRAM, 0) —— 创建一个用于 QRTR 通信的面向消息的 socket。
  • bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) —— 将 socket 绑定到本地地址,或按名称发现远端服务。
  • sendto(sockfd, data, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) —— 向目的地发送消息。
  • recvfrom(sockfd, data, len, 0, (struct sockaddr *)&src_addr, &addr_len) —— 从 socket 接收消息。
  • close(sockfd) —— 关闭 socket 并释放资源。