上次测试了,从xenomai实时层到linux普通进程之间的通信。
有朋友评论,并指出反向如何?非实时到实时进程之间的通信
并提出了非常好的一个问题,非实时进程向实时进程传说数据的时候,实时进程如何知道有数据发来,并实时响应?
第一阶段,我先研究了下,没有实时响应的情况。
第一: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 *devname;
char *buf[3]= {
"buf1",
"buf2",
"buf3"
};
char buf2[]="write to the xddp";
int n=0;
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(n;n<3;n++){
//ret=read(fd,buf,sizeof(buf));
ret=write(fd,buf2,sizeof(buf2));
{if(ret <=0)
fail("write");}
//n = (n + 1) % (sizeof(buf) / sizeof(buf[0]));
//outwrite=write(1,buf[n],sizeof(buf));
//}
exit(0);
}
第二:实时进程读取
/*
* 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 void fail(const char *reason)
{
perror(reason);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
/*
* 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.
*/
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 datagrams 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[n]);
/*
* 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[n], len, 0, NULL, 0);
if (ret != len)
fail("sendto");
rt_printf("%s: sent %d bytes, \"%.*s\"\n",
__FUNCTION__, ret, ret, msg[n]);
*/
/* 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]));
//}
return 0;
}
三:测试
四:总结
在此期间,出过一个问题。
char buf2[]="write to the xddp";
我定义为指针来char *buf2[],
在写的时候sizeof[buf2]
这样无论我的数据多长,接收到的只有前4个字符。
很简单的原因,概念不清楚。指针占用4个字节。所以才出现这样的问题。