kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。
说明关于kfifo的相关概念,有兴趣可以看相关文档,这里只将其实现过程移植重写,移植到适用stm32开发板上,并且按照个人习惯重新命名,RingBuff->意为环形缓冲区
RingBuff_t环形缓冲区的结构体成员变量,具体含义看注释。
buffer: 用于存放数据的缓存
size: buffer空间的大小
in, out: 和buffer一起构成一个循环队列。 in指向buffer中队头,而且out指向buffer中的队尾
创建一个环形缓冲区,为了适应后续对缓冲区入队出队的高效操作,环形缓冲区的大小应为2^n字节,
如果不是这个大小,则系统默认裁剪以对应缓冲区字节。
当然还可以优化,不过我目前并未做,思路如下:如果系统支持动态分配内存,则向上对齐,避免浪费内存空间,否则就按照我默认的向下对齐,当内存越大,对齐导致内存泄漏则会越多。对齐采用的函数是roundup_pow_of_two。如果系统支持互斥量,那么还将创建一个互斥量用来做互斥访问,防止多线程同时使用导致数据丢失。
删除一个环形缓冲区,删除之后,缓冲区真正存储地址是不会被改变的(目前我是使用自定义数组做缓冲区的),但是删除之后,就无法对缓冲区进行读写操作。并且如果支持os的话,创建的互斥量会被删除。
Write_RingBuff向环形缓冲区写入指定数据,支持线程互斥访问。用户想要写入缓冲区的数据长度不一定是真正入队的长度,在完成的时候还要看看返回值是否与用户需要的长度一致~
这个函数很有意思,也是比较高效的入队操作,将指定区域的数据拷贝到指定的缓冲区中,过程看注释即可
读取缓冲区数据到指定区域,用户指定读取长度,用户想要读取的长度不一定是真正读取的长度,在读取完成的时候还要看看返回值是否与用户需要的长度一致~也支持多线程互斥访问。
也是缓冲区出队的高效操作。过程看代码注释即可
这些就比较简单了,看看缓冲区可读可写的数据有多少
附带这里的代码是用于测试的,随便写的
支持多个os的互斥量操作此处模仿了文件系统的互斥操作
debug.h最后送一份debug的简便操作源码,因为前文很多时候会调用
PRINT_ERR
PRINT_DEBUG
转贴自网络