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
......
相关推荐
戏舟的嵌入式开源笔记8 小时前
RP2040(移植FreeRTOS-SMP)
rtos·嵌入式软件
W.W.H.5 天前
优先级反转问题(含解决案例)
互斥锁·rtos·互斥量·实时系统·优先级反转·优先级继承
.普通人8 天前
freertos源码解析(里面的源码来源于另一个博主,我这里只是讲一下我自己的理解)
操作系统·rtos
dqsh0611 天前
振兴中华之threadX RTOS移植到stm32用stm32cubeMX 保姆级教程
stm32·单片机·嵌入式硬件·rtos·threadx
Truffle7电子14 天前
STM32理论 —— FreeRTOS:中断管理、列表
stm32·单片机·嵌入式硬件·rtos
Truffle7电子15 天前
STM32理论 —— FreeRTOS:任务
stm32·嵌入式·rtos
大熊背19 天前
ISP离线模式应用(二)-如何利用 ISP 离线模式 加速 3DNR 收敛
linux·算法·rtos·isp pipeline·3dnr
aspirestro三水哥20 天前
9.3工欲善其事必先利其器
rtos·xenomai
逆小舟23 天前
【SWM320】FreeRTOS搭建工程——1、框架学习
嵌入式·c·rtos
aspirestro三水哥23 天前
9.4贡献自己的第一个patch
rtos·xenomai