5. ODP API 组件

ODP程序围绕几个概念进行构建,每个开发者都应该熟悉这些概念。 主要的概念主要的是:线程、事件、队列、池、共享内存、缓冲区、数据包、PktIO、定时器和同步器。

5.1. 线程(Thread)

线程是ODP中的基本编程单元。ODP应用程序被组织成执行设计工作的线程集合。 ODP线程可能或者可能不会与其他线程共享内存,这取决于具体实现。 线程有两种类型:控制线程和工作线程,他们由抽象类型 odp_thread_type_t 表示。

控制线程是组织工作线程工作的监督线程。 而工作线程则负责执行应用程序的主要逻辑,它采用的是RTC模型。 特别的是,工作线程一般运行于专用的处理核心上,特别是在多核心的处理环境中。 但是,如果需要,给定的实现可以在单核上运行(通常在较小和较低性能目标环境上)。

除了线程类型,线程还具有关联属性,例如,线程掩码和调度程序组,确定他们可以在哪里运行,以及他们可以处理的工作类型。

5.2. 事件(Event)

事件是线程执行工作的过程。事件可以表示新的工作,如需要处理的数据包到达,或者他们可以表示异步执行的请求完成。 事件还可以表示通知时间,或应用程序感兴趣的各个组件状态的更改。 事件有一个描述代表它的事件类型。 线程可以创建新事件,或消耗由他们处理的事件,或者可以对事件执行进一步处理,然后将事件传递给另一个组件以进行其他处理。 对事件的引用是通过抽象类 odp_event_t 句柄实现的。 提供了专用函数将他们转换成由事件表示的适当类型的特定句柄。

5.3. 队列(Queue)

队列是保存事件的消息传递通道。 事件可以通过入队操作添加到队列中,或者通过出队操作从队列中删除。 队列的端点将根据使用方式而有所不同。 队列有两种主要类型:轮询和调度,这将在引入事件模型时更详细的讨论。 队列也可能具有关联的上下文,这表示所有使用它的事件的持久状态。 这些状态是允许线程对事件进行有状态处理以及无状态处理。

队列由抽象类型 odp_event_t 表示。

5.4. 池(Pool)

池是元素存储的共享内存区域。Pool代表了事件及其他东西的后备存储。 池通常在应用程序初始化和终止期间内创建和销毁,在程序处理过程中被调用。 池可以由专门的ODP组件或专门的应用程序使用,或者两者共享使用。 池具有描述他们包含的元素的关联类型。两个最重要的池类型是缓冲区(buffer)和数据包(packet)。

池由抽象类型 odp_pool_t 表示。

5.5. 共享内存(Shared Memory)

共享内存表示在线程之间共享的原始存储块。 他们是池的构建块,但是如果需要,可以直接由ODP应用程序使用。

共享内存由抽象数据 odp_shm_t 表示。

5.6. 缓冲区(Buffer)

Buffer是ODP组件和应用程序用于实现其功能的固定大小的共享存储块。 Buffer包含0个或多个字节的应用程序数据以及提供有关Buffer信息的系统维护Metadata(例如buffer大小,从哪个pool分配)。 Metadata是一个重要的ODP概念,因为他允许任意数量的辅助信息与ODP对象相关联。 大多数ODP对象都有相关联的元数据,并且该元数据通过访问器函数进行操作,该函数用作此数据信息的getter和setter。 Getter操作允许应用程序读取Metadata,而Setter操作允许应用程序写入Metadata。 请注意,一些Meatdata本质上是只读的,因此没有提供Setter操作。 当对象具有多个Metadata时,每个Metadata都有自己关联的Getter和Setter访问操作。

Buffer由抽象数据类型 odp_buffer_t 表示。

5.7. 数据包(Packet)

Packet是指通过IO接口接收和发送,并表示数据面应用程序操作的基本数据。 Packet来自 ODP_POOL_PACKET 类型的Pool。 与简单的Buffer不同,ODP Packet具有丰富的语义,允许以复杂的方式进行检查和操作,这些将在后面描述。 Packet还支持丰富的Metadata以及User Metadata。 User Metadaa允许应用程序将确定的副信息量与每个Packet相关联以供自己使用。

Packet由抽象类型 odp_packet_t 表示。

5.8. 报文接口(PktIO)

PktIO是ODP表示IO接口的方式。 PktIO对象是能够接收(RX)和发送(TX)报文的逻辑端口。 这可以由基础平台作为集成功能直接支持,或者可以表示通过PCIE或其他总线连接的设备。

PktIO由抽象类型 odp_pktio_t 表示。

5.9. 时间(Time)

时间API用于测量应用程序的时间间隔和跟踪事件流程,并提供了访问时间源的便利方式。 事件API由两个主要部分组成:Local time API和Global time API。

5.9.1. 局部时间(Local time)

Local time API被设计为在一个线程内使用,并且可以比Global time API更快。 由于时间一致性不能保证,Local time API不能在线程间使用。 本地时间戳是调用线程本地的,不能与其他线程共享。 当前本地时间可以通过接口 odp_time_local() 获取。

5.9.2. 全局时间(Global time)

Global time API被设计为用于跟踪线程之间的时间。 所以,全局时间戳可以在线程之间共享。 当前全局时间可以通过接口 odp_time_global() 获取。

时间API包括随时间运行的功能,例如 odp_time_diff() odp_time_sum()odp_time_cmp() 。 时间转换函数 odp_time_to_ns() , odp_time_local_from_ns() , odp_time_global_from_ns() 。 要获取时间源使用接口 odp_time_local_res() , odp_time_global_res() 。 要等待,使用接口 odp_time_wait_ns()odp_time_wait_until() 在线程繁忙期间循环等待 。

odp_time_t 类型表示本地或全局时间戳。

5.10. 定时器(Timer)

Timer指应用程序如何衡量和相应时间的流逝。 Timer从具有自己的抽象类型 odp_timer_pool_t 的专用池(定时器池)中申请出来。 应用程序可能同时具有许多定时器活动,并可将其设置为使用相对或绝对时间。 当定时器到期时,他们会创建类型为 odp_timeout_t 的事件,这些事件作为定时器到期的通知。

5.11. 同步器(Synchronizer)

并行运行的多个线程通常需要各种同步服务,使得他们以可靠和协调的方式运行。 ODP提供了一组丰富的locks、barries,和类似的同步原语,以及用于表示各种类型的原子变量的抽象类型。 ODP事件模型还使用队列来避免在许多情况下显式加锁的需要。 这些内容将在下一节讨论。