串口缓冲区管理分析
来源:互联网 发布:mac怎么查看激活时间 编辑:程序博客网 时间:2024/04/27 20:52
一、 概述:
串口使用时一般包含两个缓冲区,即发送缓冲区和接收缓冲区。发送数据时,先将数据存在发送缓冲区,然后通过串口发送;接收数据时,先将接收的数据存在接收缓冲区,然后再进行读取。
合理恰当的使用缓冲区,不仅可以使不同设备间正常通信,而且还有助于节约内存,提高效率。
二、缓冲区分配管理:
方法一:
通过内存池实现
1、数据结构:
struct _CHN_POOL_MGR
{
u8 buffer[BUF_SZ];
u32 free_bitmap;
};
参数含义:struct _CHN_POOL_MGR:内存池的数据类型
buffer:缓冲区,大小为BUF_SZ 192
free_bitmap:标志位。
注意:缓冲区又分为若干块,每块大小BLK_SZ
free_bitmap标志缓冲区块中的空闲块和被使用块,1表示空闲,0表示被使用
注:阴影部分表示存放着数据
free_bitmap初始化为(1 << (sizeof(chn_pool_mgr.buffer) / BLK_SZ)) -1即(1 << (2^10/2^6)) -1,即二进制数11111...11111b,共16个1,缓冲区块全部空闲
alloc_a_slot()函数分配缓冲区块:检测free_bitmap值,将空闲的缓冲区块标号较小的块分配,返回分配的缓冲区块的标号
free_bitmap值
分配的缓冲区块标号
alloc_a_slot()返回值
1111...111111
0
0
1111...111100
2
2
1111...110010
1
1
1111...000100
2
2
//不是太明白????
struct _CHN_SLOT
{
s16 tx;
s16 rx;
/*the current count of this channel */
s16 data_cnt;
s16 data_max;
};
参数含义:struct _CHN_SLOT:记录缓冲区读写状态的结构体
tx:记录缓冲区块标号和数据的写入位置(具体存放如图所示)
rx:记录缓冲区块标号和数据的读取位置(具体存放如图所示)
data_cnt:记录缓冲区中未读取的数据量
data_max:向缓冲区中写入数据时,缓冲区中允许存在的最大数据量
tx,rx数据含义:
2,实例分析
1)向缓冲区中写数据:
向缓冲区中写数据,每次写90个字节,写两次。
初始状态:
假设struct _CHN_SLOT结构体中各参数均为初始状态:tx = rx = INVALID_PTR,即(INVALID_BLK_NO << BLK_NO_SHIFT),data_cnt为0,data_max为UART_MAX_LEN
内存池的状态如下:
写数据:
alloc_a_slot()分配缓冲区块:
检测free_bitmap,分配缓冲区块标号为2的块;
tx记录缓冲区块标号及写入数据位置(0x80);
缓冲区块最后一个字节置为INVALID_BLK_NO;
变为如下状态:
写入90个数据:
由于90 > BLK_SZ-1(一个块存放数据的最大字节数),所以再次调用alloc_a_slot()分配缓冲区块
检测free_bitmap,分配缓冲区块标号为4的块;
tx记录缓冲区块标号及写入数据位置(0x100);
缓冲区块最后一个字节置为INVALID_BLK_NO;
此外,还要使标号为2的块的最后一个字节记录下一块的标号(4),最后将剩余的数据写入,tx记录数据位置(0x11B)
写入完成后,各参数状态如下:
第二次写入数据:
与上面类似,根据tx记录的缓冲区块标号及数据位置继续向后写。
最终变为如下状态:
3)从缓冲区中读数据
从缓冲区中读数据,每次读40个,读完为止。
假设此时缓冲区状态,及各参数如下:
data_cnt为180
此时开始读取数据,rx记录缓冲区标号及数据位置,成功读取40个数据后变为:
继续读数据,标号为2的缓冲区块内的数据读完,由该块内最后一个字节得知下一缓冲区块的标号,rx记录,此时,各参数状态如下:
继续读取,data_cnt变为0,读取结束。
小结:
由以上分析可知,使用内存池的方法,通过检测free_bitmap可使缓冲区被多个任务共同使用,节约空间。
方法二:
利用循环队列实现
1、数据类型:
struct _CHN_SLOT
{
int tx, rx;
u8 buf[BUFFER_LEN];
};
参数含义:
tx:记录缓冲区写入位置
rx:记录缓冲区读取位置
buf:缓冲区
2、方法实现:
每存入一个字节,tx后移一位,每取走一个字节,rx后移一位
当tx移至缓冲区结尾时,若缓冲区头部已读取,则tx会继续在头部存放数据,如下:
当(rx + 1) % BUFFER_LEN == tx时,缓冲区存满
三、两种方法的比较:
比较内容
方法一
方法二(循环队列式)
使用缓冲区的任务数
允许多任务
只能单任务
空间利用率
高
低
缓冲区的使用顺序
优先使用低地址处的缓冲区块
由低地址到高地址循环使用
不能存放数据的字节数
缓冲区块数
1B
编程复杂度
略微复杂
简单
注:方法一不能存放数据的字节数用于记录下一缓冲区块的位置;循环队列式,不能存放数据的字节数用于循环使用缓冲区
方法一最大的好处在于可同时被多个任务共同使用,互不影响,有助于节约内存;而且每次分配空间时,会优先使用低地址处的空闲块,数据集中,有利于减少内存池的占用;某一任务释放的空间可被另一任务使用,提高了利用率,但编程略微复杂。
循环队列式编程简单,容易理解,特别适合单任务的使用,但缓冲区的利用率不是很高,且无法多任务使用。
- 串口缓冲区管理分析
- 串口缓冲区管理分析
- 串口缓冲区管理分析
- linux011文件系统中缓冲区管理函数分析
- 缓冲区管理
- 清空串口缓冲区
- STM32串口环形缓冲区
- 《Windows内核情景分析》系统空间缓冲区管理
- 单片机缓冲区串口读写代码
- MFC清空串口缓冲区
- 串口实用的循环缓冲区
- 自己写的串口缓冲区
- 串口实用的循环缓冲区
- 输出缓冲区的管理
- 内存和缓冲区管理
- 输出缓冲区的管理
- 输出缓冲区的管理
- 虚拟内存及缓冲区管理
- ADB工具的使用
- 纯servlet实现验证码
- http工作原理
- leetcode--Plus One
- Android电量不足提醒框
- 串口缓冲区管理分析
- Java基础(极客)——12、Java面向对象基本特征:继承
- 第九周项目 1 存储班长信息的学生类(2)
- VS2013下由于字符集不同导致的C/S通信错误解决方案
- 数据挖掘知识框架
- shell单引号、双引号和反引号的区别
- Google 镜像站搜集
- java虚拟机运行原理
- android中的shape标签