0
我需要在Xenomai機器上執行RT到NRT通信。xenomai xddp與std :: thread
我居然能編譯和運行提出here 的例子但是,如果試圖將pthreads
與std::thread
更換,具體如下:
#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>
#include <iostream>
#include <thread>
#define XDDP_PORT_LABEL "xddp-demo"
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"
};
static void fail(const char *reason) {
perror(reason);
exit(EXIT_FAILURE);
}
void realtime_thread1() {
struct rtipc_port_label plabel;
struct sockaddr_ipc saddr;
char buf[128];
int ret, s;
/*
* 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 */
ret = recvfrom(s, buf, sizeof(buf), 0, NULL, 0);
if (ret <= 0)
fail("recvfrom");
rt_printf("%s: \"%.*s\" relayed by peer\n", __FUNCTION__, ret, buf);
}
}
void realtime_thread2() {
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 peer
* 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%d\n",
__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);
}
}
void regular_thread() {
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);
std::cout << "File descriptor regular thread: " << fd << std::endl;
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");
}
}
int main(int argc, char **argv) {
std::thread rt1(realtime_thread1);
std::thread rt2(realtime_thread2);
std::thread regth(regular_thread);
rt1.join();
rt2.join();
regth.join();
return 0;
}
我在open函數,它返回會出現故障 - 1。
我想使用std::thread
的原因是我需要在C++中實現代碼,並且pthread不理解成員函數。我不想使用全局變量。
另外,我需要運行在RT和NRT相同的代碼(不xenomai庫)機,我已經準備了代碼(方便擺放#ifdef
。
從我讀過有關Xenomai它給線程個性層,如果你使用POSIX線程,這那麼C++ std :: thread會得到一個Po六層,你不能使用Xenomai功能。 –
即使使用'pthread_create()',也可以調用C++成員函數,例如,您希望在C++'std :: thread'下找到什麼? –