读取串行数据而不占用大量CPU 我想通过Linux下的简单的C或C++程序,通过FTDI(串行)接口读取从ARDUINO发送的消息。Arduino发送一个两个字符的“header”,一个命令字节,后跟取决于命令的几个字节的数据
我的第一次尝试是使用open()和read()简单地轮询数据,但这样做会导致大约12%的CPU使用。这似乎不是正确的做事方式 其次,我了解了libevent上实现的一个事件循环,该循环在文件描述符上存在数据时触发事件。我的cpu使用率几乎为零,但在调用另一个事件之前,我无法读取整个消息。当接收到整个消息时,但只要文件描述符上有任何/某些数据可用,就不会触发事件。更仔细地看,很明显,这并不是我想要的方式。这是我的活动代码: 第三,我用libevent实现了一个缓冲事件。它似乎工作得更好一些,但仍然将一些消息分割开来。我的活动代码是: 第四,我抛弃了libevent并试用了Boost的ASIO类。我举的例子是。它似乎工作正常,但“事件循环”是一个“while(1){}”,这导致CPU使用率再次上升。当串行读取在不同线程的回调中发生时,循环只检查错误状态。我在while循环中添加了一个usleep(1),它使我的CPU使用率达到了2%,这是可以的,但对于这样一个轻量级的程序来说,它似乎仍然很重 libevent的大多数示例甚至底层epoll都使用TCP套接字,其行为似乎与串行端口数据不同读取串行数据而不占用大量CPU 我想通过Linux下的简单的C或C++程序,通过FTDI(串行)接口读取从ARDUINO发送的消息。Arduino发送一个两个字符的“header”,一个命令字节,后跟取决于命令的几个字节的数据,linux,serial-port,Linux,Serial Port,我的第一次尝试是使用open()和read()简单地轮询数据,但这样做会导致大约12%的CPU使用。这似乎不是正确的做事方式 其次,我了解了libevent上实现的一个事件循环,该循环在文件描述符上存在数据时触发事件。我的cpu使用率几乎为零,但在调用另一个事件之前,我无法读取整个消息。当接收到整个消息时,但只要文件描述符上有任何/某些数据可用,就不会触发事件。更仔细地看,很明显,这并不是我想要的方式。这是我的活动代码: 第三,我用libevent实现了一个缓冲事件。它似乎工作得更好一些,但仍然
所以我的主要问题是:在没有大量轮询的情况下,从串行端口读取消息的轻量级方法是什么?(在linux中,使用C或C++)OP很可能早就解决了这个问题,但为了那些通过谷歌来到这里的人:
#include <sys/poll.h>
struct pollfd fds[1];
fds[0].fd = serial_fd;
fds[0].events = POLLIN ;
int pollrc = poll( fds, 1, 1000);
if (pollrc < 0)
{
perror("poll");
}
else if( pollrc > 0)
{
if( fds[0].revents & POLLIN )
{
char buff[1024];
ssize_t rc = read(serial_fd, buff, sizeof(buff) );
if (rc > 0)
{
/* You've got rc characters. do something with buff */
}
}
}
#包括
结构pollfd fds[1];
fds[0].fd=串行_fd;
fds[0]。事件=POLLIN;
int pollrc=轮询(fds,11000);
if(pollrc<0)
{
佩罗(“投票”);
}
else if(pollrc>0)
{
if(fds[0]。revents和POLLIN)
{
字符buff[1024];
ssize_t rc=读取(串行fd、buff、sizeof(buff));
如果(rc>0)
{
/*你有rc角色。用buff做点什么*/
}
}
}
确保串行端口在非阻塞模式下打开,因为poll()有时会在没有字符等待时返回。您使用的是非阻塞
read()
?阻塞read()
对您无效吗?调用read
是一个阻塞调用。你能证明调用read
导致了12%的CPU使用,或者你只是在看一个系统监视器吗?如果它真的是CPU密集型的,那么试着通过gprof
运行它,看看瓶颈在哪里。我通常在大多数情况下使用Qt库,但对于这个小任务来说它似乎有点重。另外,我喜欢学习API的“较低”级别。我的第一次尝试使用了阻塞读取(),而我的libevent尝试使用了非阻塞读取()。明天我将检查gprof并使用一个简单的blocking read(),然后报告我的发现。在Windows上,您可以使用低级FTDI SDK库,它完全绕过系统串行端口驱动程序。不确定它是否可以在linux上使用,但如果可以的话,你可以试一试。