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



*
 * 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 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]));
		/*
		 * 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(&regattr);
	pthread_attr_setdetachstate(&regattr, PTHREAD_CREATE_JOINABLE);
	pthread_attr_setinheritsched(&regattr, PTHREAD_EXPLICIT_SCHED);
	pthread_attr_setschedpolicy(&regattr, SCHED_OTHER);

	errno = pthread_create(&nrt, &regattr, &regular_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);
}



三:运行结果



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

祝福

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
RT-Linux(实时Linux)是一个基于Linux内核的实时操作系统,它提供了对实时性的支持。RT-Linux使用内核级线程来实现实时性,它可以在Linux内核和实时任务之间提供良好的交互。编写RT-Linux应用程序与编写普通Linux应用程序类似,但需要特别注意一些实时性相关的问题。 在RT-Linux中,可以使用POSIX实时扩展(也称为RTAI)或Xenomai框架来编写实时应用程序。这些框架提供了运行实时任务所需的API和机制,并与Linux内核进行交互。 编写RT-Linux应用程序需要考虑以下几个方面: 1. 实时任务的调度:在RT-Linux中,需要为实时任务设置优先级,并使用适当的调度策略来确保实时任务按时执行。常用的调度策略包括FIFO(先进先出)和RR(循环调度)。 2. 中断处理:实时应用程序通常需要与硬件设备进行交互,因此需要处理硬件中断。在RT-Linux中,可以使用中断处理程序来处理硬件中断,并采取适当的措施来保证实时性。 3. 实时性分析:为了确保实时任务能够按时执行,需要进行实时性分析。这包括确定任务的执行时间和响应时间,并根据实时性要求进行优化。 4. 同步和通信:在多个实时任务之间进行同步和通信是很常见的需求。RT-Linux提供了各种同步和通信机制,如信号量、互斥锁和消息队列等,可以用于实现任务之间的数据共享和通信。 总之,RT-Linux编程需要对实时性要求有一定的了解,并使用适当的编程技术和工具来满足这些要求。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值