C 与 C++ 实现

1. C 实现的定位

Aeron 的 C 代码不是 Java 的 JNI 封装,而是独立、完整的实现,与 Java 版本共享相同的协议和数据结构定义。两者可以互操作——Java Driver 可以服务 C Client,反之亦然。

┌──────────────────┐          ┌─────────────────────┐
│   应用 (C)        │          │   应用 (Java)        │
├──────────────────┤          ├─────────────────────┤
│  aeron_client    │          │  aeron-client       │
│  (C)             │          │  (Java)             │
├──────────────────┤          ├─────────────────────┤
│        │         │          │        │            │
│  ┌─────▼──────────────────────────▼─────┐         │
│  │      共享内存 (CNC + Log Buffers)     │         │
│  ├──────────────────────────────────────┤         │
│  │  aeron_driver (C)  or  MediaDriver (Java)     │
│  └──────────────────────────────────────┘         │
└───────────────────────────────────────────────────┘

C 实现的典型使用场景:

  • 低延迟交易系统:避免 Java GC 停顿
  • 嵌入式设备:资源受限环境
  • FFI 集成:C ABI 可从 Rust、Go、Python 等直接调用

2. C 模块结构

C 代码分布在各模块的 src/main/c/ 路径下,~150 个 .c 文件 + ~150 个 .h 文件:

aeron-client/src/main/c/
├── aeronc.h              # C 客户端主头文件(公开 API)
├── aeron_client.c         # Client 实现
├── aeron_publication.c    # Publication
├── aeron_subscription.c   # Subscription
├── aeron_client_conductor.c # 客户端协调器
├── concurrent/            # Lock-Free 数据结构
│   ├── aeron_mpsc_rb.c   # Multi-Producer Single-Consumer Ring Buffer
│   ├── aeron_spsc_rb.c   # Single-Producer Single-Consumer Ring Buffer
│   ├── aeron_broadcast_receiver.c
│   ├── aeron_broadcast_transmitter.c
│   ├── aeron_atomic.c    # 原子操作封装(CAS, Fence)
│   └── aeron_logbuffer_descriptor.c
├── collections/           # 自定义集合类型
│   ├── aeron_int64_to_ptr_hash_map.c
│   ├── aeron_str_to_ptr_hash_map.c
│   └── aeron_bit_set.c
├── protocol/              # 协议 flyweight(C 版本)
│   └── aeron_udp_protocol.c
├── util/                  # 工具函数
│   ├── aeron_error.c
│   ├── aeron_clock.c
│   ├── aeron_parse_util.c
│   └── aeron_netutil.c
└── uri/                   # URI 解析
    └── aeron_uri.c

aeron-driver/src/main/c/
├── aeronmd.h              # C 驱动主头文件(公开 API)
├── aeron_driver.c         # Driver 入口
├── aeron_driver_conductor.c # 驱动协调器
├── aeron_driver_sender.c  # 发送器
├── aeron_driver_receiver.c # 接收器
├── aeron_flow_control.c   # 流控
├── aeron_congestion_control.c # 拥塞控制
├── aeron_publication_image.c # 镜像接收
├── aeron_ipc_publication.c   # IPC 发布
├── aeron_network_publication.c # 网络发布
├── aeron_loss_detector.c  # 丢包检测
├── aeron_retransmit_handler.c # 重传处理
├── agent/                 # Agent 线程模型
│   └── aeron_driver_agent.c
├── media/                 # UDP 传输层
│   ├── aeron_udp_channel.c
│   ├── aeron_send_channel_endpoint.c
│   ├── aeron_receive_channel_endpoint.c
│   └── aeron_udp_channel_transport.c
├── concurrent/            # 驱动特有的 lock-free 结构
│   └── aeron_logbuffer_unblocker.c
└── uri/                   # URI 解析(驱动侧)
    └── aeron_driver_uri.c

3. C Client API:与 Java 的对应关系

3.1 公开 API

aeronc.h 是 C 客户端的公共头文件:

// 创建和配置
aeron_context_t *aeron_context_init(aeron_context_t *context);
aeron_t *aeron_init(aeron_t *client, aeron_context_t *context);
aeron_t *aeron_connect(aeron_t *client);

// Publication
aeron_publication_t *aeron_add_publication(
    aeron_t *client, const char *channel, int32_t stream_id);
int64_t aeron_publication_offer(
    aeron_publication_t *publication,
    const uint8_t *buffer, size_t length,
    aeron_reserved_value_supplier_t reserved_value_supplier, void *clientd);

// Subscription
aeron_subscription_t *aeron_add_subscription(
    aeron_t *client, const char *channel, int32_t stream_id,
    aeron_on_available_image_t on_available_image,
    void *on_available_image_clientd,
    aeron_on_unavailable_image_t on_unavailable_image,
    void *on_unavailable_image_clientd);
int aeron_subscription_poll(
    aeron_subscription_t *subscription,
    aeron_fragment_handler_t handler, void *clientd, size_t fragment_limit);

// 事件循环驱动
int aeron_client_conductor_do_work(aeron_client_conductor_t *conductor);

3.2 Java ↔ C 对应表

概念 Java C
Client 入口 Aeron.connect(ctx) aeron_connect(client)
配置 Aeron.Context aeron_context_t
发布 Publication.offer() aeron_publication_offer()
订阅 Subscription.poll() aeron_subscription_poll()
协调器 ClientConductor.doWork() aeron_client_conductor_do_work()
Atomic CAS Unsafe.compareAndSwapLong() aeron_cmpxchg64()
Volatile Read Unsafe.getLongVolatile() aeron_get_volatile64()
RingBuffer (MPSC) ManyToOneRingBuffer aeron_mpsc_rb_t

3.3 原子操作封装

concurrent/aeron_atomic.c 封装跨平台的原子操作:

// CAS
int64_t aeron_cmpxchg64(volatile int64_t *ptr, int64_t expected, int64_t desired);

// 内存屏障
void aeron_lock_signal_fence();   // store fence (sfence / dmb)
void aeron_lock_load_fence();     // load fence (lfence / dmb)
void aeron_lock_full_fence();     // full fence (mfence / dmb)

// Volatile 读写
int64_t aeron_get_volatile64(volatile int64_t *src);
void aeron_put_volatile64(volatile int64_t *dst, int64_t value);

底层实现在不同平台:

  • Linux x86:使用 __sync_bool_compare_and_swap / __sync_synchronize
  • ARM:使用 __atomic_compare_exchange_n / __atomic_thread_fence
  • MSVC:使用 InterlockedCompareExchange64 / _ReadWriteBarrier

4. C 驱动实现

4.1 入口与线程模型

aeronmd.h 是 C 驱动的公共头文件。C 驱动支持四种线程模式 aeronmd.h:56-63

模式 说明
AERON_THREADING_MODE_DEDICATED 三独立线程(Conductor/Sender/Receiver),与 Java 默认相同
AERON_THREADING_MODE_SHARED_NETWORK Sender + Receiver 共享同一线程
AERON_THREADING_MODE_SHARED Conductor + Sender + Receiver 全部共享线程
AERON_THREADING_MODE_INVOKER 手动驱动(不创建线程)

4.2 驱动启动

aeron_driver.c

aeron_driver_context_init(&context);          // 创建配置上下文
aeron_driver_context_set_dir(&context, "/dev/shm/aeron");  // 设置目录
aeron_driver_init(&driver, &context);         // 初始化驱动
aeron_driver_start(driver, false, false);     // 启动线程/手动驱动
// ... 运行时 ...
aeron_driver_close(driver);                  // 停止并清理

4.3 驱动协调器

aeron_driver_conductor.c 是 C 驱动中最复杂的文件,与 Java DriverConductor 对应:

aeron_driver_conductor_do_work(conductor)
  ├── aeron_mpsc_rb_read(to_driver_commands)  // 读取客户端命令
  ├── 命令处理
  │   ├── AERON_COMMAND_ADD_PUBLICATION
  │   │   ├── aeron_ipc_publication_create() 或
  │   │   └── aeron_network_publication_create()
  │   ├── AERON_COMMAND_REMOVE_PUBLICATION
  │   ├── AERON_COMMAND_ADD_SUBSCRIPTION
  │   └── AERON_COMMAND_REMOVE_SUBSCRIPTION
  ├── 周期性任务(定时器到期时)
  │   ├── 客户端心跳超时检查
  │   ├── Publication 空闲超时
  │   └── 命名解析更新
  └── 资源清理

4.4 C 驱动 Sender

aeron_driver_sender.c

aeron_driver_sender_do_work(sender)
  ├── 处理命令队列 (来自 conductor)
  ├── 轮询所有 aeron_network_publication_t
  │   └── aeron_network_publication_send()
  │       ├── 检查 term buffer tail counter
  │       ├── 组装协议头 (DataHeader)
  │       ├── sendmsg() 系统调用
  │       └── 更新 sender position
  ├── 检查 aeron_retransmit_handler_t (NAK 重传)
  └── 流控检查

4.5 C 驱动 Receiver

aeron_driver_receiver.c

aeron_driver_receiver_do_work(receiver)
  ├── 处理命令队列
  ├── epoll / kqueue / select (跨平台 I/O 多路复用)
  │   └── 对每个就绪的 receive_channel_endpoint:
  │       └── recvmsg() → on_data_packet()
  │           ├── 解析 DataHeader
  │           ├── 查找/创建 aeron_publication_image_t
  │           ├── 写入 image 的 term buffer
  │           └── LossDetector 扫描
  ├── 轮询所有 publication_image
  │   └── aeron_publication_image_send_status_message()
  │       ├── 组装 Status Message 帧
  │       └── sendmsg() 发送
  └── 清理 PendingSetup

5. C++ 示例

C++ 示例位于 aeron-samples/src/main/cpp/,使用 C API 的简单 C++ 包装:

C++ 示例通过 extern "C" 包含 C 头文件,无额外的 C++ 中间层封装。


6. 构建系统

C/C++ 代码使用 CMake 构建,顶层 CMakeLists.txt 管理:

cmake 选项:
  BUILD_AERON_DRIVER=ON              ← 构建 C 驱动
  BUILD_AERON_ARCHIVE_API=ON         ← 构建 Archive C 客户端
  AERON_TESTS=ON                     ← 构建测试(使用 Google Test)
  AERON_BUILD_SAMPLES=ON             ← 构建示例

构建依赖:

  • Google Test 1.14.0(自动下载)
  • HdrHistogram_c 0.11.9(自动下载)
  • C11 编译器(GCC/Clang/MSVC)+ CMake 3.13+

7. 关键设计决策

决策 实现
C 独立实现 不依赖 JNI,共享协议和内存布局定义
跨平台原子操作 aeron_cmpxchg64() 封装 x86/ARM/MSVC 差异
POSIX I/O sendmsg/recvmsg + epoll/kqueue/select
手动内存管理 C 风格 _init/_close 生命周期,无 GC
四种线程模式 从 Dedicated 到 Invoker,灵活适配场景
C++ 示例仅薄封装 直接 extern "C" 包含 C 头文件

8. Java 与 C 实现的同步

Java 和 C 实现通过以下方式保持一致性:

  1. 协议帧格式:DataHeader、StatusMessage、NAK 等帧结构在 Java(protocol/*.java)和 C(protocol/aeron_udp_protocol.c)中独立定义,但字段偏移和大小严格一致
  2. CNC 文件布局CncFileDescriptorJavaC 中独立定义
  3. LogBuffer 元数据偏移:每个字段的偏移量在两端保持一致
  4. 版本号version.txt 统一定义,Java 和 C 构建时分别读取

9. 关键源文件索引

C Client

文件 说明
aeronc.h C 客户端公开 API 头文件
aeron_client.c Client 主实现
aeron_publication.c Publication 实现
aeron_subscription.c Subscription 实现
aeron_client_conductor.c 客户端协调器
aeron_atomic.c 原子操作封装

C Driver

文件 说明
aeronmd.h C 驱动公开 API 头文件
aeron_driver.c Driver 主入口
aeron_driver_conductor.c 驱动协调器
aeron_driver_sender.c 发送器
aeron_driver_receiver.c 接收器
aeron_flow_control.c 流控

本站访问量

This site uses Just the Docs, a documentation theme for Jekyll.