linux内核的队列实现移植
来源:互联网 发布:网络剧 有毒 第一集 编辑:程序博客网 时间:2024/06/08 06:08
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
0 0
- linux内核的队列实现移植
- linux内核队列实现
- Linux 内核的队列实现--kfifo
- Linux 内核的队列实现--kfifo
- linux内核的移植
- linux内核的移植
- linux内核移植的问题
- mini2440的 linux内核移植
- mini2440的Linux内核移植
- ARM9的linux内核移植
- mini2440 的Linux 内核移植
- rk3188--12.linux内核中工作队列的实现
- Linux内核的等待队列
- Linux内核的等待队列
- Linux内核的等待队列
- linux内核的工作队列
- Linux内核的等待队列
- Linux内核的等待队列
- 面向对象
- 贾跃亭对乐视员工的公开信
- Windows 2012 ASP.NET安裝經驗一則
- Servlet过滤和监听器
- Android研发安全3-Service安全
- linux内核的队列实现移植
- 构造函数
- Qt下载网络文件
- 并发编程——并行级别
- 多文件导出为ZIP文件
- 数组工具对象建立
- 移动应用渗透测试的军火库清单
- 使用Python完成机器学习算法之Logistic Regression
- 在 Alpine Linux 上编译 Linux0.11 内核