linux内核的队列实现移植
linux内核的队列实现移植
[!TOC]
在c编程中有时会使用一些常用的数据结构,如队列。每次都手写一遍有些麻烦,写一个通用的比较好,而内核有实现队列,直接移植出来就好了。
内核的队列实现
内核的队列实现在linux-2.6.32.68/kernel/kfifo.c和对应的kfifo.h中,主要接口罗列如下:
struct kfifo {unsigned char *buffer; /* the buffer holding the data */unsigned int size; /* the size of the allocated buffer */unsigned int in; /* data is added at offset (in % size) */unsigned int out; /* data is extracted from off. (out % size) */spinlock_t *lock; /* protects concurrent modifications */ };extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,spinlock_t *lock); extern void kfifo_free(struct kfifo *fifo); static inline void kfifo_reset(struct kfifo *fifo); static inline unsigned int kfifo_put(struct kfifo *fifo,const unsigned char *buffer, unsigned int len); static inline unsigned int kfifo_get(struct kfifo *fifo,unsigned char *buffer, unsigned int len); static inline unsigned int kfifo_len(struct kfifo *fifo);
函数名字已非常清晰的表明了用途,无需多言。说一下,它的实现里面我觉得比较好的几个点。
- 内核实现的亮点
较我自己以前实现的队列而言,在队列发生循环时,会通过取余的方式去更新队尾和队头下标。这样队尾下标有可能比队头下标小。计算队列长度时,相减又需要考虑此种情况。
而内核in和out是一直递增的(因为是无符号,溢出也没关系),put和get时通过fifo->in & (fifo->size - 1)
方式取余计算,分开拷贝。内核的put核心代码如下:
unsigned int __kfifo_put(struct kfifo *fifo,const unsigned char *buffer, unsigned int len) {unsigned int l;len = min(len, fifo->size - fifo->in + fifo->out);/* first put the data starting from fifo->in to buffer end */l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);/* then put the rest (if any) at the beginning of the buffer */memcpy(fifo->buffer, buffer + l, len - l);fifo->in += len;return len; }
移植
移植到普通应用,可以视情况去掉还是保留锁机制,在这儿就去掉了,再替换掉一些kmalloc这样的内核函数,实现is_power_of_2和roundup_pow_of_two两个函数就可以了。为了通用性,fifo.c里的代码都是对char型指针结合长度参数进行写入读取,而在自己使用时,可以在fifo.h里封装一下,方便自己的数据存放和读取。我在测试时封装成了存取int整数。
fifo.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "fifo.h"static inline int is_power_of_2(unsigned int n) {return !((n - 1) & n); }unsigned int roundup_pow_of_two(unsigned int n) {if(is_power_of_2(n))return n;int i = 32;while(i--){if((n >> i) & 1)break;}n = 1 << (i + 1);return n; } struct fifo *fifo_init(unsigned char *buffer, unsigned int size) {struct fifo *fifo;fifo = malloc(sizeof(struct fifo));if (!fifo){fprintf(stderr, "malloc %ubyte failed\n", sizeof(struct fifo));return NULL;}fifo->buffer = buffer;fifo->size = size;fifo->in = fifo->out = 0;return fifo; }struct fifo *fifo_alloc(unsigned int size) {unsigned char *buffer;struct fifo *ret;/* round up to the next power of 2 */if(size > 0x80000000){fprintf(stderr, "The size is too lager\n");return NULL;}size = roundup_pow_of_two(size);buffer = malloc(size);if (!buffer){fprintf(stderr, "malloc %ubyte failed\n", size);return NULL;}ret = fifo_init(buffer, size);if (!ret)free(buffer);return ret; }void fifo_free(struct fifo *fifo) {free(fifo->buffer);free(fifo); }unsigned int _fifo_put(struct fifo *fifo, const unsigned char *buffer, unsigned int len) {unsigned int l;len = min(len, fifo->size - fifo->in + fifo->out);/* first put the data starting from fifo->in to buffer end */l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);/* then put the rest (if any) at the beginning of the buffer */memcpy(fifo->buffer, buffer + l, len - l);fifo->in += len;return len; }unsigned int _fifo_get(struct fifo *fifo, unsigned char *buffer, unsigned int len) {unsigned int l;len = min(len, fifo->in - fifo->out);/* first get the data from fifo->out until the end of the buffer */l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);/* then get the rest (if any) from the beginning of the buffer */memcpy(buffer + l, fifo->buffer, len - l);fifo->out += len;return len; }
fifo.h
#ifndef _FIFO_H_ #define _FIFO_H_struct fifo {unsigned char *buffer; /* the buffer holding the data */unsigned int size; /* the size of the allocated buffer */unsigned int in; /* data is added at offset (in % size) */unsigned int out; /* data is extracted from off. (out % size) */ };#define min(a, b) ((a) > (b) ? (b) : (a))extern struct fifo *fifo_alloc(unsigned int size); extern void fifo_free(struct fifo *fifo); extern unsigned int _fifo_put(struct fifo *fifo, const unsigned char *buffer, unsigned int len); extern unsigned int _fifo_get(struct fifo *fifo,unsigned char *buffer, unsigned int len);static inline void _fifo_reset(struct fifo *fifo) {fifo->in = fifo->out = 0; }static inline unsigned int _fifo_len(struct fifo *fifo) {return fifo->in - fifo->out; }/****************************************************/ /* 根据需要进行封装,这儿我封装为保存int数 /****************************************************/static inline void fifo_reset(struct fifo *fifo) {_fifo_reset(fifo); }static inline unsigned int fifo_len(struct fifo *fifo) {return _fifo_len(fifo)/4; }static inline unsigned int fifo_put(struct fifo *fifo, int n) {return _fifo_put(fifo, (unsigned char *)&n, sizeof(int)); }static inline unsigned int fifo_get(struct fifo *fifo, int *n) {return _fifo_get(fifo, (unsigned char *)n, sizeof(int)); }#endif
linux内核的队列实现移植相关推荐
- Linux内核的裁剪和移植
linux内核的裁剪和移植具体都在这个网址里面. https://blog.csdn.net/xie0812/article/details/10816059 https://blog.csdn.ne ...
- 话说linux内核-uboot和系统移植第14部分-朱有鹏-专题视频课程
话说linux内核-uboot和系统移植第14部分-5304人已学习 课程介绍 本课程为linux kernel移植的第1部分,主要内容是对linux内核有关的知识和概念的补充.认识清 ...
- 基于ARM的嵌入式linux 内核的裁剪与移植
0 引言 微处理器的产生为价格低廉.结构小巧的CPU和外设的连 接提供了稳定可靠的硬件架构,这样,限制嵌入式系统发展的瓶颈就突出表现在了软件方面.尽管从八十年代末开始,已经陆续出现了一些嵌入式 ...
- linux内核的裁剪和移植实验,实验5 linux内核的裁剪移植.doc
实验5 linux内核的裁剪移植 一.实验目的: 学习利用menuconfig配置文件进行裁减内核,编译内核并移植到开发板上. 二.实验内容 一.开发环境 宿主机:ubuntu10.04 开发板:ti ...
- 移植linux内核-映像文件,移植Linux内核-映像文件
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://tigerwang202.blogbus.com/logs/43927976.html 首先从Blackfin uCli ...
- STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- linux内核多队列,Linux Kernel 中 Workqueue 使用系统默认队列和创建队列的方法
关于workqueue,我们还是有很多话要说. 想必大家对workqueue相关的函数(schedule_work .queue_work.INIT_WORK.create_singlethread_ ...
- Linux内核RED队列实现
关于RED队列的TC配置命令,参见:RED队列tc设置. 1 RED入队列 首先计算平均队列长度qavg,参见之后函数red_calc_qavg的介绍.如果队列处于空闲状态,退出空闲状态,清空空闲开始 ...
- linux 内核主线,为AM335x移植Linux内核主线代码(41)Ethernet结论篇
一口老血喷到屏幕上! 请自动略过之前的第36-40小节=_=!!! ===================================== https://www.tuicool.com/arti ...
最新文章
- Oracle to_char函数的使用方法
- windows mobile开发循序渐进(5)移动应用程序与webservice之间的数据交互
- mysql弱口令加强_MySQL弱口令利用
- 一起撸个朋友圈吧(step5) - 控件篇【评论控件优化】
- undi是什么意思_undefined是什么意思啊
- [Swift]数组排序:sort和sorted
- 在Teams Hackathon上介绍LuckyDraw
- MAVEN简介之——settings.xml
- 大家一起讨论一下朋友网的人脉关系算法是怎么实现的
- FFmpeg总结(二)AV系列结构体之AVFrame
- 国密SM2算法的只求理解不求甚解 (3/5)SM2算法数学模型
- c语言将一句英文逆序输出,C++实现英文句子中的单词逆序输出的方法
- JavaScript复习,this指向、原型链、变量提升、作用域、闭包
- Cassandra启动过程详解【原创】
- 小白一看就懂的性能调优
- 天翼云携手华为,强强联合,共创数据存储新生态
- LaTex关于数学公式的使用(7)--- 函数单边大括号
- 30多种免费的高级WordPress主题,适用于令人惊叹的照片,教育和房地产网站
- 阿里云为啥在云服务器市场输给腾讯云
- CV2逐步学习-2:cv2.GaussianBlur()详解
热门文章
- matlab中round函数_Excel中round函数的使用方法
- TF-IDF算法-golang实现
- 【新手向】阿里云上ubuntu+flask+gunicorn+nginx服务器部署(二)项目部署
- 软件工程网络15个人阅读作业1(201521123062 杨钧宇)
- Jmeter-Ant 生成测试报告
- 图 | 为什么存在关于图的研究
- su root 后还是不能使用useradd ,useradd 等命令
- javascript 200列(3)
- 文件上传 文件大小和类型
- 【Vue】—Vue脚手架创建项目时的 linter / formatter config配置选择