Xenomai XDDP example and Posix Compling
1 firstly we give the function:
/* realtime_thread1----------------------------->----------+
* => get socket |
* => bind socket to port "xddp-demo |
* => read traffic from NRT domain via recvfrom() <--+--+
* | |
* realtime_thread2----------------------------------------+ |
* => get socket | |
* => connect socket to port "xddp-demo" | |
* => write traffic to NRT domain via sendto() v |
* | ^
* regular_thread------------------------------------------+ |
* => open /proc/xenomai/registry/rtipc/xddp/xddp-demo | |
* => read traffic from RT domain via read() | |
* => mirror traffic to RT domain via write() +--+
*/
2 The codes are as follows:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <malloc.h>
#include <pthread.h>
#include <fcntl.h>
#include <errno.h>
#include <rtdm/ipc.h>
pthread_t rt1, rt2, nrt;
#define XDDP_PORT_LABEL "rt_arm"
static const char *msg[] = {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"A",
"B",
"C",
"D",
"E",
"F"
};
static void fail(const char *reason)
{
perror(reason);
exit(EXIT_FAILURE);
}
static void *realtime_thread1(void *arg) //sensor data
{
struct rtipc_port_label plabel;
struct sockaddr_ipc saddr;
char buf[128];
int ret, s;
int err;
struct timespec next_period;
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &next_period);
//err=rt_task_set_periodic(1000);
/*
* Get a datagram socket to bind to the RT endpoint. Each
* endpoint is represented by a port number within the XDDP
* protocol namespace.
*/
s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP);
if (s < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
/*
* Set a port label. This name will be registered when
* binding, in addition to the port number (if given).
*/
strcpy(plabel.label, XDDP_PORT_LABEL);
ret = setsockopt(s, SOL_XDDP, XDDP_LABEL,
&plabel, sizeof(plabel));
if (ret)
fail("setsockopt");
/*
* Bind the socket to the port, to setup a proxy to channel
* traffic to/from the Linux domain. Assign that port a label,
* so that peers may use a descriptive information to locate
* it. For instance, the pseudo-device matching our RT
* endpoint will appear as
* /proc/xenomai/registry/rtipc/xddp/<XDDP_PORT_LABEL> in the
* Linux domain, once the socket is bound.
*
* saddr.sipc_port specifies the port number to use. If -1 is
* passed, the XDDP driver will auto-select an idle port.
*/
memset(&saddr, 0, sizeof(saddr));
saddr.sipc_family = AF_RTIPC;
saddr.sipc_port = -1;
ret = bind(s, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret)
fail("bind");
for (;;) {
/* Get packets relayed by the regular thread */
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_period, NULL);
ret = recvfrom(s, buf, sizeof(buf), 0, NULL, 0);
clock_gettime(CLOCK_MONOTONIC, &time);
if (ret <= 0)
fail("recvfrom");
rt_printf("%s: "%.*s" relayed by peern", __FUNCTION__, ret, buf);
}
return NULL;
}
static void *realtime_thread2(void *arg) // Loop
{
struct rtipc_port_label plabel;
struct sockaddr_ipc saddr;
int ret, s, n = 0, len;
struct timespec ts;
struct timeval tv;
socklen_t addrlen;
s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_XDDP);
if (s < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
/*
* Set the socket timeout; it will apply when attempting to
* connect to a labeled port, and to recvfrom() calls. The
* following setup tells the XDDP driver to wait for at most
* one second until a socket is bound to a port using the same
* label, or return with a timeout error.
*/
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
&tv, sizeof(tv));
if (ret)
fail("setsockopt");
/*
* Set a port label. This name will be used to find the pee
* when connecting, instead of the port number.
*/
strcpy(plabel.label, XDDP_PORT_LABEL);
ret = setsockopt(s, SOL_XDDP, XDDP_LABEL,
&plabel, sizeof(plabel));
if (ret)
fail("setsockopt");
memset(&saddr, 0, sizeof(saddr));
saddr.sipc_family = AF_RTIPC;
saddr.sipc_port = -1; /* Tell XDDP to search by label. */
ret = connect(s, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret)
fail("connect");
/*
* We succeeded in making the port our default destination
* address by using its label, but we don't know its actual
* port number yet. Use getpeername() to retrieve it.
*/
addrlen = sizeof(saddr);
ret = getpeername(s, (struct sockaddr *)&saddr, &addrlen);
if (ret || addrlen != sizeof(saddr))
fail("getpeername");
rt_printf("%s: NRT peer is reading from /dev/rtp%dn",
__FUNCTION__, saddr.sipc_port);
for (;;) {
len = strlen(msg[n]);
/*
* Send a datagram to the NRT endpoint via the proxy.
* We may pass a NULL destination address, since the
* socket was successfully assigned the proper default
* address via connect(2).
*/
ret = sendto(s, msg[n], len, 0, NULL, 0);
if (ret != len)
fail("sendto");
rt_printf("%s: sent %d bytes, "%.*s"n",
__FUNCTION__, ret, ret, msg[n]);
n = (n + 1) % (sizeof(msg) / sizeof(msg[0]));
/*
* We run in full real-time mode (i.e. primary mode),
* so we have to let the system breathe between two
* iterations.
*/
ts.tv_sec = 0;
ts.tv_nsec = 500000000; /* 500 ms */
clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
}
return NULL;
}
static void *regular_thread(void *arg)
{
char buf[128], *devname;
int fd, ret;
if (asprintf(&devname,
"/proc/xenomai/registry/rtipc/xddp/%s",
XDDP_PORT_LABEL) < 0)
fail("asprintf");
fd = open(devname, O_RDWR);
free(devname);
if (fd < 0)
fail("open");
for (;;) {
/* Get the next message from realtime_thread2. */
ret = read(fd, buf, sizeof(buf));
if (ret <= 0)
fail("read");
/* Relay the message to realtime_thread1. */
ret = write(fd, buf, ret);
if (ret <= 0)
fail("write");
}
return NULL;
}
int main(int argc, char **argv)
{
struct sched_param rtparam = { .sched_priority = 42 };
pthread_attr_t rtattr, regattr;
sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGHUP);
pthread_sigmask(SIG_BLOCK, &set, NULL);
pthread_attr_init(&rtattr);
pthread_attr_setdetachstate(&rtattr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setinheritsched(&rtattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&rtattr, SCHED_FIFO);
pthread_attr_setschedparam(&rtattr, &rtparam);
/* Both real-time threads have the same attribute set. */
errno = pthread_create(&rt1, &rtattr, &realtime_thread1, NULL);
if (errno)
fail("pthread_create");
errno = pthread_create(&rt2, &rtattr, &realtime_thread2, NULL);
if (errno)
fail("pthread_create");
pthread_attr_init(®attr);
pthread_attr_setdetachstate(®attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setinheritsched(®attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(®attr, SCHED_OTHER);
errno = pthread_create(&nrt, ®attr, ®ular_thread, NULL);
if (errno)
fail("pthread_create");
sigwait(&set, &sig);
pthread_cancel(rt1);
pthread_cancel(rt2);
pthread_cancel(nrt);
pthread_join(rt1, NULL);
pthread_join(rt2, NULL);
pthread_join(nrt, NULL);
return 0;
}
3 The compiler, Makefile
target = rt_p1
skin = posix
#skin = vxworks
CC := $(shell /usr/xenomai/bin/xeno-config --cc)
CFLAGS := $(shell /usr/xenomai/bin/xeno-config --skin=$(skin) --cflags)
LDFLAGS := $(shell /usr/xenomai/bin/xeno-config --skin=$(skin) --ldflags)
$(target): $(target).c
$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
clean:
@rm $(target)
4 the previous configuration
sudo chmod 777 /dev/rtdm/memdev-shared
sudo chmod 777 /dev/rtdm/memdev-private
sudo chmod 777 /dev/rtp0
5 run
sudo su
./rt_p1
The results are
realtime_thread2: NRT peer is reading from /dev/rtp0
realtime_thread2: sent 1 bytes, "1"
realtime_thread1: "1" relayed by pee
realtime_thread2: sent 1 bytes, "2"
realtime_thread1: "2" relayed by pee
realtime_thread2: sent 1 bytes, "3"
realtime_thread1: "3" relayed by pee
realtime_thread2: sent 1 bytes, "4"
realtime_thread1: "4" relayed by pee
realtime_thread2: sent 1 bytes, "5"
realtime_thread1: "5" relayed by pee
realtime_thread2: sent 1 bytes, "6"
realtime_thread1: "6" relayed by pee
realtime_thread2: sent 1 bytes, "7"
realtime_thread1: "7" relayed by pee
realtime_thread2: sent 1 bytes, "8"
realtime_thread1: "8" relayed by pee
realtime_thread2: sent 1 bytes, "9"
realtime_thread1: "9" relayed by pee
realtime_thread2: sent 2 bytes, "10"
realtime_thread1: "10" relayed by pee
^Crealtime_thread2: sent 1 bytes, "A"
realtime_thread1: "A" relayed by pee
realtime_thread2: sent 1 bytes, "B"
realtime_thread1: "B" relayed by pee
realtime_thread2: sent 1 bytes, "C"
realtime_thread1: "C" relayed by pee
realtime_thread2: sent 1 bytes, "D"
realtime_thread1: "D" relayed by pee
6 Have a good fun!
- Membership三步曲之入门篇 - Membership基础示例
- Java-String.intern的深入研究
- 从Membership 到 .NET4.5 之 ASP.NET Identity
- Membership三步曲之进阶篇 - 深入剖析Provider Model
- java finally深入探究
- 背后的故事之 - 快乐的Lambda表达式(一)
- 背后的故事之 - 快乐的Lambda表达式(二)
- JVM GC杂谈之理论入门
- 线程池定制初探
- 由浅入深表达式树(二)遍历表达式树
- 由浅入深表达式树(一)创建表达式树
- 重读算法导论之算法基础
- 算法之数组和问题
- 由浅入深表达式树(完结篇)重磅打造 Linq To 博客园
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- iOS逆向开发(7):微信伪装他人
- 因为喜欢所以升级,MyStaging-3.0 继续
- 环境与工具篇:建立高效的macos环境
- 0202年你还不知道面向对象?
- 十问泛型,你能扛住吗?
- 【两万字】面试官:听说你精通集合源码,接我二十个问题!
- 手把手教你搭建一个技术人的博客
- 发布更新|腾讯云 Serverless 产品动态 20200723
- Spring中异步注解@Async的使用、原理及使用时可能导致的问题
- Elasticsearch 聚合数据结果不精确,怎么破?
- Elasticsearch 预处理没有奇技淫巧,请先用好这一招!
- 时滞微分方程的matlab解法
- Zabbix Monitoring Logstash
- Join()和 List()的 6 种化学反应
- lettuce和hbase中对netty的使用你都了解吗?