您的位置:首页 > 运维架构 > Linux

xenomai与普通linux进程之间通信——XDDP(RT->nRT)

qianshanxue11 2016-08-09 19:33 162 查看

*

 * XDDP-based RT/NRT threads communication demo.

 *

 * Real-time Xenomai threads and regular Linux threads may want to

 * exchange data in a way that does not require the former to leave

 * the real-time domain (i.e. secondary mode). Message pipes - as

 * implemented by the RTDM-based XDDP protocol - are provided for this

 * purpose.

 *

 * On the Linux domain side, pseudo-device files named /dev/rtp<minor>

 * give regular POSIX threads access to non real-time communication

 * endpoints, via the standard character-based I/O interface. On the

 * Xenomai domain side, sockets may be bound to XDDP ports, which act

 * as proxies to send and receive data to/from the associated

 * pseudo-device files. Ports and pseudo-device minor numbers are

 * paired, meaning that e.g. port 7 will proxy the traffic for

 * /dev/rtp7. Therefore, port numbers may range from 0 to

 * CONFIG_XENO_OPT_PIPE_NRDEV - 1.

 *

 * All data sent through a bound/connected XDDP socket via sendto(2) or

 * write(2) will be passed to the peer endpoint in the Linux domain,

 * and made available for reading via the standard read(2) system

 * call. Conversely, all data sent using write(2) through the non

 * real-time endpoint will be conveyed to the real-time socket

 * endpoint, and made available to the recvfrom(2) or read(2) system

 * calls.

xenomai的例程是两个线程之间通信。

我想写成两个程序之间的通信,xenomai将数据传输到XDDP_PORT

这里设置/dev/rtp0

实时进程将数据传到这里之后,普通进程就可以像访问其他文件一样,直接访问了。

一:xenomai端源代码

/*
* XDDP-based RT/NRT threads communication demo.
*
* Real-time Xenomai threads and regular Linux threads may want to
* exchange data in a way that does not require the former to leave
* the real-time domain (i.e. secondary mode). Message pipes - as
* implemented by the RTDM-based XDDP protocol - are provided for this
* purpose.
*
* On the Linux domain side, pseudo-device files named /dev/rtp<minor>
* give regular POSIX threads access to non real-time communication
* endpoints, via the standard character-based I/O interface. On the
* Xenomai domain side, sockets may be bound to XDDP ports, which act
* as proxies to send and receive data to/from the associated
* pseudo-device files. Ports and pseudo-device minor numbers are
* paired, meaning that e.g. port 7 will proxy the traffic for
* /dev/rtp7. Therefore, port numbers may range from 0 to
* CONFIG_XENO_OPT_PIPE_NRDEV - 1.
*
* All data sent through a bound/connected XDDP socket via sendto(2) or
* write(2) will be passed to the peer endpoint in the Linux domain,
* and made available for reading via the standard read(2) system
* call. Conversely, all data sent using write(2) through the non
* real-time endpoint will be conveyed to the real-time socket
* endpoint, and made available to the recvfrom(2) or read(2) system
* calls.
*
* Both threads can use the bi-directional data path to send and
* receive datagrams in a FIFO manner, as illustrated by the simple
* echoing process implemented by this program.
*
* realtime_thread------------------------------>-------+
*   =>  get socket                                     |
*   =>  bind socket to port 0                          v
*   =>  write traffic to NRT domain via sendto()       |
*   =>  read traffic from NRT domain via recvfrom() <--|--+
*                                                      |  |
* regular_thread---------------------------------------+  |
*   =>  open /dev/rtp0                                 |  ^
*   =>  read traffic from RT domain via read()         |  |
*   =>  echo traffic back to RT domain via write()     +--+
*
* See Makefile in this directory for build directives.
*
* NOTE: XDDP is a replacement for the legacy RT_PIPE interface
* available from the native skin until Xenomai 3.
*/
#include <sys/mman.h>
#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 <rtdk.h>
#include <rtdm/rtipc.h>

pthread_t rt, nrt;

#define XDDP_PORT 0	/* [0..CONFIG-XENO_OPT_PIPE_NRDEV - 1] */

static const char *msg[] = {
// "Surfing With The Alien",
"HanQi love you, be with you \n",
"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"
};

static void fail(const char *reason)
{
perror(reason);
exit(EXIT_FAILURE);
}

static void *realtime_thread(void *arg)
{
struct sockaddr_ipc saddr;
int ret, s, n = 0, len;
struct timespec ts;
size_t poolsz;
char buf[128];

/*
* 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 local 16k pool for the RT endpoint. Memory needed to
* convey data
4000
grams will be pulled from this pool, instead of
* Xenomai's system pool.
*/
poolsz = 16384; /* bytes */
ret = setsockopt(s, SOL_XDDP, XDDP_POOLSZ,
&poolsz, sizeof(poolsz));
if (ret)
fail("setsockopt");

/*
* Bind the socket to the port, to setup a proxy to channel
* traffic to/from the Linux domain.
*
* saddr.sipc_port specifies the port number to use.
*/
memset(&saddr, 0, sizeof(saddr));
saddr.sipc_family = AF_RTIPC;
saddr.sipc_port = XDDP_PORT;
ret = bind(s, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret)
fail("bind");

for (;;) {
len = strlen(msg
);
/*
* Send a datagram to the NRT endpoint via the proxy.
* We may pass a NULL destination address, since a
* bound socket is assigned a default destination
* address matching the binding address (unless
* connect(2) was issued before bind(2), in which case
* the former would prevail).
*/
ret = sendto(s, msg
, len, 0, NULL, 0);
if (ret != len)
fail("sendto");

rt_printf("%s: sent %d bytes, \"%.*s\"\n",
__FUNCTION__, ret, ret, msg
);

/* Read back packets echoed by the regular thread */
/*	ret = recvfrom(s, buf, sizeof(buf), 0, NULL, 0);
if (ret <= 0)
fail("recvfrom");

rt_printf("   => \"%.*s\" echoed by peer\n", ret, buf);

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, "/dev/rtp%d", XDDP_PORT) < 0)
fail("asprintf");
/*
fd = open(devname, O_RDWR);
free(devname);
if (fd < 0)
fail("open");

for (;;) {
/* Get the next message from realtime_thread. */
/*		ret = read(fd, buf, sizeof(buf));
if (ret <= 0)
fail("read");

/* Echo the message back to realtime_thread. */
/*		ret = write(fd, buf, ret);
if (ret <= 0)
fail("write");
}
*/
return NULL;
}

static void cleanup_upon_sig(int sig)
{
pthread_cancel(rt);
pthread_cancel(nrt);
signal(sig, SIG_DFL);
pthread_join(rt, NULL);
pthread_join(nrt, NULL);
}

int main(int argc, char **argv)
{
struct sched_param rtparam = { .sched_priority = 42 };
pthread_attr_t rtattr, regattr;
sigset_t mask, oldmask;

mlockall(MCL_CURRENT | MCL_FUTURE);

sigemptyset(&mask);
sigaddset(&mask, SIGINT);
signal(SIGINT, cleanup_upon_sig);
sigaddset(&mask, SIGTERM);
signal(SIGTERM, cleanup_upon_sig);
sigaddset(&mask, SIGHUP);
signal(SIGHUP, cleanup_upon_sig);
pthread_sigmask(SIG_BLOCK, &mask, &oldmask);

/*
* This is a real-time compatible printf() package from
* Xenomai's RT Development Kit (RTDK), that does NOT cause
* any transition to secondary (i.e. non real-time) mode when
* writing output.
*/
rt_print_auto_init(1);

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);

errno = pthread_create(&rt, &rtattr, &realtime_thread, 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");

sigsuspend(&oldmask);

return 0;
}


二:普通linux程序

#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define XDDP_PORT 0

static void fail(const char *reason)
{
perror(reason);
exit(EXIT_FAILURE);
}

int main()
{

char buf[128],*devname;
memset(buf,0,sizeof(buf));
int fd, ret,outwrite;
if(asprintf(&devname,"dev/rtp%d",XDDP_PORT)<0)
fail("asprintf");
fd = open("/dev/rtp0", O_RDWR);
free(devname);
if(fd<0)
fail("open rtp0");
//out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
//while(read(in,&c,1) == 1)
// write(out,&c,1);
for(;;){
ret=read(fd,buf,sizeof(buf));
if(ret <=0)
fail("read");

outwrite=write(1,buf,sizeof(buf));
//puts(buf);

}

exit(0);
}



三:运行结果




今天七夕。所以把输出特意写成这样。

祝福
标签: