在读取串口数据的时候,因为上位机读取速度和下位机发送速率之间的差异,如果仅仅使用read读取数据就需要循环去读取,非阻塞的read读取到数据或者到文件末尾就返回了,这就造成系统以很快的频率去读取串口且很多情况下都可能是读不到数据的情况(因为上位机的速率远高于下位机),也就造成了性能的浪费,如下所示:
while(1)
{
......
int ReadNum = read(fd, package_data, BUFFER_SIZE); //读到文件末尾即结束
}
而如果使用阻塞式的read虽然能提高一定的性能,因为上位机读取的速度非常快,所以基本上每次只能读取一个字节就又要阻塞了,在性能的利用上也不是很高效;而使用select监听串口的话,在阻塞了指定的时候后,如果在串口检测到有数据传输,则此时执行读取操作; 因为在select阻塞的时候程序会被挂起,所以不会消耗cpu的时间片,所以能够提升系统运行的性能,以下是一个demo
bool Serial::get_data(int fd)
{
unsigned char package_data[BUFFER_SIZE]{};
bool readFlag = true;
int readcount = 0;
fd_set rfds;
struct timeval tv;
while(1)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100000; //100ms
int ret = select(fd + 1, &rfds, NULL, NULL, &tv); //程序会在此阻塞100ms,阻塞期间不占用cpu
if (-1 == ret)
{
printf("Error occur. \n");
return false;
}
else if (0 == ret)
{
printf("No data get during 100ms \n");
continue;
}
int ReadNum = read(fd, package_data, BUFFER_SIZE);
......
}
}
参考文章:
1.简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
2.linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例
网友评论