株洲市网站建设_网站建设公司_Tailwind CSS_seo优化
2026/1/12 12:05:08 网站建设 项目流程

6.6 RTIPC之BUFP实例分析

实时进程或实时线程之间,可以使用 RTIPC BUFP 协议通信。 BUFP 是面向字节的流式缓存通信机制,可以多次向缓存区发送不同数量的字节数据。

BUFP 有如下特性:

  • 缓冲区管理:必须通过setsockopt + IPCPROTO_BUFP申请缓冲区。缓冲区的分配实际上在bind操作中完成,所以应在bind之前申请缓冲区。
  • 端口号:使用数字端口号管理,支持动态端口号分配
  • 端口标签化(Labeled Port):为端口赋予可读名称(如"bufp-demo"),通过名称连接。

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

特性bufp-readwrite.cbufp-label.c
寻址方式指定端口号通过标签动态查找端口
连接模式类连接(connect+write/read类连接(connect+write/read
缓存区分配16KB缓冲区分配16KB缓冲区

6.6.1 BUFP 无连接实时通信

1. 代码概述

bufp-readwrite.c是一个基于 BUFP 协议的实时通信示例,通过SOCK_DGRAM套接字类型实现数据报传输。与iddp-sendrecv.c不同,该程序使用read()/write()代替sendto()/recvfrom(),并通过connect()在客户端固定目标地址,简化了数据收发逻辑。核心功能包括:实时线程创建、内存池配置、数据报的流式读写。

  1. 头文件包含
  • 关键头文件<rtdm/ipc.h>:提供 Xenomai 实时 IPC 支持。
  • 其他标准头文件:包括线程、信号、字符串处理等(如<pthread.h>,<signal.h>)。
  1. 全局变量与常量
  • 线程标识符pthread_t svtid, cltid分别标识服务器和客户端线程。
  • 端口定义BUFP_SVPORT 12定义服务器绑定的实时端口。
  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. 信号屏蔽:屏蔽SIGINTSIGTERMSIGHUP信号,避免中断线程。
  2. 线程属性配置
    • 服务器线程优先级设为71,客户端线程优先级70
    • 调度策略均为SCHED_FIFO(先进先出实时调度)。
  3. 线程创建
    • 创建服务器线程server和客户端线程client
  4. 信号等待与清理:通过sigwait等待信号,取消线程并回收资源。
3.server服务器线程
  1. 创建套接字
    ints=socket(AF_RTIPC,SOCK_DGRAM,IPCPROTO_BUFP);
  2. 配置缓冲区大小
    bufsz=16384;// 16KB 缓冲区setsockopt(s,SOL_BUFP,BUFP_BUFSZ,&bufsz,sizeof(bufsz));
  3. 绑定端口:绑定到BUFP_SVPORT(端口 12)。
  4. 接收数据
    • 通过read()循环读取数据,打印接收到的字节数和内容。
    ret=read(s,buf,sizeof(buf));printf("received %d bytes, \"%.*s\"\n",ret,ret,buf);
4.client客户端线程
  1. 创建套接字并连接
    s=socket(AF_RTIPC,SOCK_DGRAM,IPCPROTO_BUFP);connect(s,(structsockaddr*)&svsaddr,sizeof(svsaddr));
    • 使用connect()固定目标地址为服务器端口BUFP_SVPORT
  2. 发送数据
    • 通过write()发送消息数组中的字符串,循环切换消息。
    ret=write(s,msg[n],strlen(msg[n]));printf("sent %d bytes, \"%.*s\"\n",ret,ret,msg[n]);
  3. 休眠控制:每次发送后休眠 500 毫秒,避免过度占用 CPU。
    structtimespects={.tv_nsec=500000000};// 500 msclock_nanosleep(CLOCK_REALTIME,0,&ts,NULL);
5. 运行输出示例

从运行输出可以观察到,客户端不断向流式缓冲区写入字符串,而服务器端一次性从缓冲区读取所有换成的字符串。

# ./bufp-readwriteclient: sent22bytes,"Surfing With The Alien"client: sent14bytes,"Lords of Karma"client: sent12bytes,"Banana Mango"client: sent13bytes,"Psycho Monkey"client: sent21bytes,"Luminous Flesh Giants"client: sent15bytes,"Moroccan Sunset"client: sent12bytes,"Satch Boogie"server: received128bytes,"Surfing With The AlienLords of KarmaBanana MangoPsycho MonkeyLuminous Flesh GiantsMoroccan SunsetSatch BoogieFlying In A Blue Dr"client: sent22bytes,"Flying In A Blue Dream"client: sent4bytes,"Ride"client: sent11bytes,"Summer Song"client: sent14bytes,"Speed Of Light"client: sent14bytes,"Crystal Planet"client: sent21bytes,"Raspberry Jam Delta-V"client: sent10bytes,"Champagne?"client: sent26bytes,"Clouds Race Across The Sky"client: sent19bytes,"Engines Of Creation"server: received128bytes,"eamRideSummer SongSpeed Of LightCrystal PlanetRaspberry Jam Delta-VChampagne?Clouds Race Across The SkyEngines Of CreationSurfin"......

6.6.2 BUFP 标签化实时通信

1. 代码概述

bufp-label.c是一个基于 BUFP 协议的实时通信示例,通过端口标签(Label)机制实现动态端口发现。与bufp-readwrite.c不同,该程序使用标签(而非固定端口号)标识通信端点,服务器绑定到动态分配的端口并通过标签注册,客户端通过标签查找服务器端口。核心功能包括:标签绑定、动态端口分配、基于标签的端点发现。

  1. 头文件包含
  • bufp-readwrite.c相同,包含<rtdm/ipc.h>等实时 IPC 和线程操作头文件。
  1. 全局变量与常量
  • 标签定义BUFP_PORT_LABEL "bufp-demo"定义服务端和客户端共用的标签。
#defineBUFP_PORT_LABEL"bufp-demo"
  1. 数据结构
  • 端口标签结构体struct rtipc_port_label用于设置标签选项。
structrtipc_port_label{charlabel[32];// 标签名称(最大 31 字符 + 终止符)};
  1. 消息数组msg[]包含客户端发送的字符串消息,与之前示例一致。
2.main函数分析
  • 线程属性与信号处理:与bufp-readwrite.c完全一致,服务器线程优先级71,客户端70
3.server服务器线程
  1. 创建套接字
    ints=socket(AF_RTIPC,SOCK_DGRAM,IPCPROTO_BUFP);
  2. 配置缓冲区大小:设置BUFP_BUFSZ16KB
  3. 绑定标签
    structrtipc_port_labelplabel;strcpy(plabel.label,BUFP_PORT_LABEL);setsockopt(s,SOL_BUFP,BUFP_LABEL,&plabel,sizeof(plabel));
    • 标签"bufp-demo"在绑定后注册到 Xenomai 的 BUFP 注册表中。绑定后的标签会出现在/proc/xenomai/registry/rtipc/bufp目录中。
  4. 动态端口绑定
    saddr.sipc_port=-1;// 由系统自动分配空闲端口bind(s,(structsockaddr*)&saddr,sizeof(saddr));
  5. 接收数据:通过read()循环读取数据并打印。
4.client客户端线程
  1. 创建套接字并设置标签
    structrtipc_port_labelplabel;strcpy(plabel.label,BUFP_PORT_LABEL);setsockopt(s,SOL_BUFP,BUFP_LABEL,&plabel,sizeof(plabel));
  2. 通过标签连接服务器
    structsockaddr_ipcsvsaddr;svsaddr.sipc_port=-1;// 告知 BUFP 通过标签查找端口connect(s,(structsockaddr*)&svsaddr,sizeof(svsaddr));
  3. 发送数据:循环发送消息数组中的字符串,每次发送后休眠 500 毫秒。
5. 运行输出示例

从运行输出可以观察到,客户端不断向流式缓冲区写入字符串,而服务器端一次性从缓冲区读取所有换成的字符串。

# ./bufp-labelclient: sent22bytes,"Surfing With The Alien"client: sent14bytes,"Lords of Karma"client: sent12bytes,"Banana Mango"client: sent13bytes,"Psycho Monkey"client: sent21bytes,"Luminous Flesh Giants"client: sent15bytes,"Moroccan Sunset"client: sent12bytes,"Satch Boogie"server: received128bytes,"Surfing With The AlienLords of KarmaBanana MangoPsycho MonkeyLuminous Flesh GiantsMoroccan SunsetSatch BoogieFlying In A Blue Dr"client: sent22bytes,"Flying In A Blue Dream"client: sent4bytes,"Ride"client: sent11bytes,"Summer Song"client: sent14bytes,"Speed Of Light"client: sent14bytes,"Crystal Planet"client: sent21bytes,"Raspberry Jam Delta-V"client: sent10bytes,"Champagne?"client: sent26bytes,"Clouds Race Across The Sky"client: sent19bytes,"Engines Of Creation"server: received128bytes,"eamRideSummer SongSpeed Of LightCrystal PlanetRaspberry Jam Delta-VChampagne?Clouds Race Across The SkyEngines Of CreationSurfin"......

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询