标题:解决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秒,它也无法自动释放,这样就会导致在串口通信过程中程序会假死或出现一些其他问题。因此,我们需要为不同的应用场景选择不同大小的缓存区。

相关问题拓展阅读:

如何在linux命令中删除缓存

#清理Linux系统缓存

# echo 1 > /proc/sys/vm/drop_caches

注:1>. /proc是一个虚拟消梁搜文件系统,可以通过对它的读写操作作为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。也就是说我们可以通过调整/proc/sys/vm/drop_caches来释放内存。

0 – 不释放

1 – 释放页缓存

2 – 释放文渣胡件节点缓存和目录项缓存

3 – 释放所有缓存

# sysctl -p

#查看拿历剩余内存

# free -m

totalusedfree shared buffers cached

Mem:

-/+ buffers/cache:

Swap:

#清理Linux系统缓存

# echo 1 > /proc/sys/vm/drop_caches

注:1>. /proc是一个虚拟文件系统,可以通过对它的读写操作作为与kernel实体间进行通信的一镇腊种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。也就是说我们可以通过调整/proc/sys/vm/drop_caches来释放内存。

0 – 不释放

1 – 释放页缓存搏旅枯

2 – 释放文件节点缓存和目录项缓存

3 – 释放所有缓存基洞

# sysctl -p

#查看剩余内存

# free -m

totalusedfree shared buffers cached

Mem:

-/+ buffers/cache:

Swap:

Linux中的缓冲区和缓存内存有什么区别

缓冲镇瞎区与特定的块设备相肆锋关联,包括文件系统元数据的缓存以及页面跟踪。缓存只御雹空包含已停放的文件数据。

也就是说,缓冲区记住目录中的内容、文件权限是什么,并跟踪从某个块设备中写入或读取到哪些内存。

缓存只包含文件本身的内容。

在Linux系统下,我们一般不需要去释放内存,因为系统已经将内存管理的很好。但是凡事也有例拿枝烂外,有的时候内存会被缓存占用掉,导致系统使用SWAP空间影响性能,此时就需要执行释放内存(清理缓存)的操作了。

Linux系统的缓存机制是相当先进的,他会针对dentry(用于VFS,加速文件路径名到inode的转换)、Buffer Cache(针对磁盘块的读写)和Page Cache(针对文件inode的读写)进行缓存操作。但是在进行了大量文件操作之后,缓消漏存会把内存资源基本用光。但实际上我们文件操作已经完成,这部分缓存已经用不到了。这个时候,我们难道只能眼睁睁的看着缓存把内存空间占据掉么?

所以,我们还是有必要来手动进行Linux下释放内存的操作,其实也就是释放缓存的操作了。

要达到释放缓存的目搭档的,我们首先需要了解下关键的配置文件/proc/sys/vm/drop_caches。这个文件中记录了缓存释放的参数,默认值为0,也就是不释放缓存。他的值可以为0~3之间的任意数字,代表着不同的含义:

0 – 不释放

1 – 释放页缓存

2 – 释放dentries和inodes

3 – 释放所有缓存

知道了参数后,我们就可以根据我们的需要,使用下面的指令来进行操作。

首先我们需要使用sync指令,将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件。否则在释放缓存的过程中,可能会丢失未保存的文件。

#sync

接下来,我们需要将需要的参数写进/proc/sys/vm/drop_caches文件中,比如我们需要释放所有缓存,就输入下面的命令:

#echo 3 > /proc/sys/vm/drop_caches

此指令输入后会立即生效,可以查询现在的可用内存明显的变多了。

要查询当前缓存释放的参数,可以输入下面的指令:

#cat /proc/sys/vm/drop_caches

#free -m

对于清除swap,只有先关闭swap了,用:

#swapoff -a

而后启用swap,因为只是清除,不是说不要用swap的嘛 :

#swapon -a

Linux 自动释放内存脚本

发表于119 天前 ? 技术文章 ? 暂无评论

脚本下载

脚本内容:

#! /bin/bash

# cache释放:

# To free pagecache:

sync

sync

#echo 1 > /proc/sys/vm/drop_caches

# To free dentries and inodes:

#echo 2 > /proc/sys/vm/drop_caches

# To free pagecache, dentries and inodes:

echo 3 > /proc/sys/vm/drop_caches

# 说明,释放前更好sync一下,防止丢数据。

利用系统crontab实现每天自动运行:

crontab -e

输入以下内容:

00 00 * * * /root/Cached.sh

每天0点释放一次内存,这个时间可以根据自己需要自行设置,我的服务器情况是每天自动释放一次就OK了

在设置这个脚本的时候,发生了一系列的问题

在测试运行./Cached.sh时提示错误:Permission denied 权限的问题

解决方法:

chmod +x .Cached.sh

chmod 777 Cached.sh

接着又出现错误提示:/bin/bash^M: bad interpreter: No such file or directory

这是因为在windows下编辑的.sh文件编码格式和linux下不一样,转换一下编码格式即可:

dos2unix Cached.sh

关于linux 串口缓存空的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 标题:解决Linux串口缓存空闲问题 (linux 串口缓存空)