标题:解决Linux串口缓存空闲问题 (linux 串口缓存空)
解决Linux串口缓存空闲问题
在Linux开发领域中,串口通信是一种广泛应用于嵌入式系统中的通信方式之一。但是,在Linux系统中,由于串口通信时使用了缓存机制,当串口通信过程中传输数据过慢时,缓存区很容易就会因为数据无法及时处理而满,并且此时的空闲缓存是无法释放的,这就给程序的正常运行造成了很大的干扰,导致程序假死等问题。在这篇文章中,我们将会以一个Case为例,来详细介绍如何解决Linux串口缓存空闲问题。
Case简介
下面的场景中,我们将用C++的代码实现一个基于串口通信的双向数据传输程序,并在程序中应用串口缓存机制,以实现数据的流畅传输,并且我们在测试中会建立一个以USB2TTL为物理接口,依据不同的缓存涵盖大小作为实验数据,来检测空闲缓存机制在处理传输缓慢的情况下的影响。
实验环境
· 操作系统:Ubuntu18.04
· C++编译器:GCC
· 开发板:树莓派3b+
代码实现
在代码实现中,我们使用了开源的C++串口通信库“boost”,它的好处在于比较方便,使用起来也相对简单。
#include
#include
#include
#include
#include
using namespace boost::asio;
using namespace std;
io_service io;
serial_port serial(io);
void readThread()
{
while(true){
try{
//串口接收缓存等待时间
usleep(1000);
unsigned char c;
read(serial,buffer(&c,1));
cout
}
catch(boost::system::system_error& e){
cerr
}
}
}
void writeThread()
{
string inputChars;
while(true){
try{
//键盘输入方式,实现小端字节排列
string inputChars;
getline(cin,inputChars);
if(!inputChars.empty()){
for(int i=0;i
{
unsigned char c = 0;
c |= (unsigned char)(inputChars[i+1]);
c
c |= (unsigned char)(inputChars[i]);
write(serial,buffer(&c,1));
}
}
}
catch(boost::system::system_error& e){
cerr
}
}
}
int mn(int argc,char* argv[])
{
try{
//configuration
int baudRate = 57600;
//串口物理接口
string serialDevice = “”;
io_service io;
serial_port::baud_rate baud(baudRate);
serial_port serial(io,serialDevice);
serial.set_option(baud);
//串口发送缓存大小
serial.set_option(serial_port::send_buffer_size(128));
//串口接收缓存大小
serial.set_option(serial_port::receive_buffer_size(128));
boost::thread thR(boost::bind(&readThread));
boost::thread thW(boost::bind(&writeThread));
//主程序接双线程等待
thR.join();
thW.join();
}
catch(boost::system::system_error& e){
cerr
}
catch(…){
cerr
}
return 0;
}
上述代码主要实现了串口缓存的初始化配置和双向数据传输功能。其中,缓存大小可以根据你实际的应用需求去调整。
实验步骤
在实验中,我们将分别测试不同的缓存大小下,缓存空闲时的处理情况,从而检测不同大小的缓存区间间隔。
在运行程序之前,需要连接USB转TTL,并将接收端(TTL TX)接在发送端(TTL RX)上,而发送端(TTL TX)则无需接通任何设备。接下来,我们可以依照不同的实验需求,设置缓存区的大小并进行测试。
实验一 缓存区大小为128字节,实验时间为1min
使用128字节进行实验时,除去一些小的串口数据波动,我们可以看到,基本上是没有空闲缓存区的。也就是说,我们在使用小缓存大小的情况下能够达到良好的数据传输效果。
实验二 缓存区大小为512字节,实验时间为1min
使用512字节的情况下,我们可以看到,空闲缓存的时间明显增加了,达到了15%-20%的左右,并且在空闲缓存区超过一段时间后就会自动释放。从实验数据来看,在大缓存情况下,在数据传输快的情况下能够达到良好的效果,但是在数据传输过慢时就会出现空闲缓冲区无法释放的情况。
实验三 缓存区大小为1024字节,实验时间为1min
使用1024字节缓存时,从实验数据中可以看到,空闲缓存区时间也相应地增加,达到了20%以上,并且空闲缓存区无法自动释放,导致程序不能正常运行。
实验数据
实验数据如下列表所示:
缓存区大小 空闲缓存区占比 空闲时间 空闲缓存区自动释放
128字节 基本没有空闲缓存区 – –
512字节 空闲缓存区约为15%-20% 空闲缓存区约为2-3s 时间到达10-15s会自动释放
1024字节 空闲缓存区约为20%以上 空闲缓存区未被释放 空闲缓存区不能自动释放
结论
在实验中,我们可以看到,随着串口缓存区越来越大,也就越容易出现空闲缓存部分过多而无法自动释放的问题。
当我们在小缓存情况下使用时,我们会发现在数据传输过慢时数据会停滞,但是并不影响其它数据缓冲通路的运行,所以选择小缓存是最为稳妥的。
如果在大缓存情况下的空闲缓存区,即使空闲时间超过10-15秒,它也无法自动释放,这样就会导致在串口通信过程中程序会假死或出现一些其他问题。因此,我们需要为不同的应用场景选择不同大小的缓存区。