6.7RTIPC之XDDP实例分析

6.7 RTIPC之XDDP实例分析

XDDP 跨域数据报协议,允许线程在 Xenomai 域与 Linux 域之间通过消息管道(Message pipes)通信,且实时任务不会离开 Xenomai 域,不会影响实时性。

XDDP 有如下特性:

  • 通信机制
    • 支持数据报通信,类似于 IDDP;
    • 支持流式缓存区通信,类似于 BUFP。
  • 内存空间管理 :内存空间的分配实际上在 bind 操作中完成,所以应在 bind 之前申请本地内存池。
    • 数据报通信机制中,可通过 setsockopt + XDDP_POOLSZ 申请本地内存池,不使用 Xenomai 系统内存池。
    • 流式缓存通信机制中,必须通过 setsockopt + XDDP_BUFSZ 申请缓冲区。
  • 端口号:使用数字端口号管理,支持动态端口号分配
  • 端口标签化(Labeled Port) :为端口赋予可读名称(如"iddp-demo"),通过名称连接。

Xenomai 源码 demo/posix/cobalt 目录自带了示例程序,非常完整的演示上述特性。

特性 xddp-echo.c xddp-stream.c xddp-label.c
寻址方式 指定端口号 指定端口号 通过标签动态查找端口
通信机制 数据报 流式缓存区 数据报
连接模式 无连接 无连接 无连接
内存空间 单独申请独立内存池 xddp-pool 本地缓存区 使用 Xenomai 系统内存池 system heap (默认)

6.7.1 XDDP 实时/非实时端口通信:xddp-echo.c

1. 代码概述

本程序演示了Xenomai实时线程与Linux常规线程通过XDDP协议进行双向通信的过程。实时线程通过XDDP套接字发送数据,常规线程通过字符设备文件先读后写,实现数据回显功能。如下图所示,共经历发送接收回送回收共 4 个步骤。

  1. 头文件包含

代码开始部分包含了多个头文件,用于标准输入输出、线程操作、实时 IPC(进程间通信)、以及一些其他必要的系统功能。其中,<rtdm/ipc.h> 是与 Xenomai 实时数据分发协议相关的头文件。

  1. 全局变量与常量
c 复制代码
pthread_t rt, nrt;   // 实时线程和常规线程句柄
  • pthread_t rt, nrt;:定义了两个线程变量,用于标识实时线程和常规线程。

  • XDDP_PORT:定义了实时线程端口号,也是常规线程打开设备时使用的次设备号。

    #define XDDP_PORT 0 // 通信端口号(端口号0对应/dev/rtp0)

  1. 消息数组

msg[] 数组包含了一系列字符串消息。这些消息将用于演示实时和常规线程之间的通信。

复制代码
static const char *msg[] = {
	"Surfing With The Alien",
	"Lords of Karma",
	"Banana Mango",
	"Psycho Monkey",
	"Luminous Flesh Giants",
	"Moroccan Sunset",
	"Satch Boogie",
	"Flying In A Blue Dream",
	"Ride",
	"Summer Song",
	"Speed Of Light",
	"Crystal Planet",
	"Raspberry Jam Delta-V",
	"Champagne?",
	"Clouds Race Across The Sky",
	"Engines Of Creation"
};
2. main函数流程
  1. 信号屏蔽:阻塞SIGINT/SIGTERM/SIGHUP信号
  2. 线程属性配置:
    • 实时线程:调度策略设为 SCHED_FIFO 策略,优先级为 42。
    • 常规线程,调度策略设为 SCHED_OTHER 策略。
  3. 线程创建:分别启动实时线程和常规线程
  4. 信号等待:主线程阻塞等待终止信号
  5. 资源回收:取消线程并等待退出
3. realtime_thread 实时线程
  1. 创建XDDP套接字:

    c 复制代码
    socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP)
  2. 配置内存池:

    c 复制代码
    setsockopt(XDDP_POOLSZ, 16KB)  // 专用内存池避免系统资源竞争
  3. 绑定端口:

    c 复制代码
    bind(port=0)  // 对应/dev/rtp0设备
  4. 数据收发循环:

    c 复制代码
    sendto()发送预设消息 -> recvfrom()接收回显数据
    clock_nanosleep(500ms)  // 让渡出部分实际给其它任务
4. regular_thread 常规线程
  1. 打开字符设备:

    c 复制代码
    open("/dev/rtp0", O_RDWR)
  2. 数据回显循环:

    c 复制代码
    read()接收实时数据 -> write()原样回写
6. 运行及输出

程序输出示例:

复制代码
./xddp-echo
realtime_thread: sent 22 bytes, "Surfing With The Alien"
   => "Surfing With The Alien" echoed by peer
realtime_thread: sent 14 bytes, "Lords of Karma"
   => "Lords of Karma" echoed by peer
realtime_thread: sent 12 bytes, "Banana Mango"
   => "Banana Mango" echoed by peer
......

观察内存池,其独立申请了 xddp-pool@0 内存池,没有使用 system heap

复制代码
# cat /proc/xenomai/heap
    TOTAL      FREE  NAME
  4194304   4183872  system heap
    16384     16384  debug log
   262144    261968  shared heap
   262144    262112  private heap[314]
    16384     16384  xddp-pool@0

6.7.2 xddp-stream.c XDDP流式传输示例分析

1. 代码概述

XDDP 除了发送数据报文外,还可以通过端口以字节流模式传输数据。当需要向Linux域发送的数据无需保持消息边界时,这种模式能有效提升带宽利用率并降低传输开销。

当使用 setsockopt + XDDP_BUFSZ 为套接字设置非零缓冲区大小时将启用此功能。任何发送函数中传递 MSG_MORE 标志,数据会持续累积至流缓冲区,直到在满足以下任一条件:

  • Linux域接收端被唤醒并开始消费数据(xddp-stream.c 演示的场景)
  • 不同源端口尝试向同一目标端口发送数据
  • 发送标志中未包含 MSG_MORE

xddp-stream.c 开启了 XDDP 流式传输功能,通过 MSG_MORE 标志实现消息分片聚合传输,展示了大数据量传输场景下的优化方法。实时线程使用分散写入方式发送消息,常规线程先读后写,实现数据回显功能。如下图所示,共经历发送接收回送回收共 4 个步骤。

2. 与 xddp-echo.c 相比的变化点

xddp-echo.c 相比,只有 realtime_thread 实时线程发生了变化:

  1. 流式缓冲区配置:

    c 复制代码
    setsockopt(XDDP_BUFSZ=1024)  // 设置1KB流式缓冲区
  2. 分片发送机制:

    c 复制代码
    for(b=0; b<len; b++) {
        sendto(msg[n]+b, 1, MSG_MORE)  // 分片发送单字节
    }
3. 运行及输出
复制代码
./xddp-stream
realtime_thread: sent (scattered) 22-bytes message, "Surfing With The Alien"
   => "Surfing With The Alien" echoed by peer
realtime_thread: sent (scattered) 14-bytes message, "Lords of Karma"
   => "Lords of Karma" echoed by peer
realtime_thread: sent (scattered) 12-bytes message, "Banana Mango"
   => "Banana Mango" echoed by peer
......

6.7.3 xddp-label.c XDDP标签化通信示例分析

1. 代码概述

本示例引入端口标签机制,演示了Xenomai实时线程与Linux常规线程通过XDDP协议进行双向通信的过程。系统包含两个实时线程(收发分离)和一个常规线程(消息环回),形成双向通信环路。如下图所示,共经历发送接收回送回收共 4 个步骤。

2. 与 xddp-echo.c 相比的变化点
  1. 新增标签定义
c 复制代码
#define XDDP_PORT_LABEL "xddp-demo"  // 语义化端口标识
  1. 单个实时线程拆分成两个实时线程
  • realtime_thread1

    • 创建标签化监听端口
      • setsockopt(XDDP_LABEL): 内核注册标签
      • bind(sipc_port=-1): 自动分配物理端口
    • 持续接收常规线程转发的数据
  • realtime_thread2

    • 动态发现标签端口
      • connect(XDDP_LABEL): 连接标签
      • getpeername(): 获取实际端口号
    • 定时发送测试消息
  1. regular_thread
    • 通过/proc接口访问标签端口:/proc/xenomai/registry/rtipc/xddp/xddp-demo
    • 从 realtime_thread2 接收,转发到 realtime_thread1,实现消息环回。
3. 运行及输出

realtime_thread2 连接到 realtime_thread1 创建的标签化端口时,才会开始发送。并且在发送之前,打印出标签实际对应的动态分配的端口号。

注意,实际在常规线程中打开的是 /proc/xenomai/registry/rtipc/xddp/xddp-demo,并不是 /dev/rtp0

复制代码
./xddp-label
realtime_thread2: NRT peer is reading from /dev/rtp0
realtime_thread2: sent 22 bytes, "Surfing With The Alien"
realtime_thread1: "Surfing With The Alien" relayed by peer
realtime_thread2: sent 14 bytes, "Lords of Karma"
realtime_thread1: "Lords of Karma" relayed by peer
realtime_thread2: sent 12 bytes, "Banana Mango"
realtime_thread1: "Banana Mango" relayed by peer
......
相关推荐
切糕师学AI7 天前
NuttX RTOS是什么?
嵌入式·rtos
aspirestro三水哥8 天前
6.4非POSIXskin进程间通信
rtos·xenomai
aspirestro三水哥9 天前
6.2POSIX线程间通信
rtos·xenomai
鸿蒙小白龙10 天前
OpenHarmony轻量系统(Hi3861)RTOS API开发详解
openharmony·rtos·liteos·轻量系统
无聊到发博客的菜鸟19 天前
STM32 手册寄存器属性
stm32·单片机·嵌入式·rtos·寄存器
aspirestro三水哥19 天前
5.3RTDM用户层驱动
rtos·xenomai
无聊到发博客的菜鸟19 天前
STM32 RTC时钟不准的问题
stm32·嵌入式·rtc·rtos
aspirestro三水哥22 天前
4.7POSIX进程与线程实例
rtos·xenomai
无聊到发博客的菜鸟22 天前
使用STM32对SD卡进行性能测试
stm32·单片机·rtos·sd卡·fatfs