Linux 内核的队列实现--kfifo

今天研读了2.6.26内核的kfifo代码,感觉实现得巧妙,队列的队头队尾下标不受队列长度的限制,就算队头下标大于队列长度,也一样可以使用,原理就在于,数据不是全部放在队头(fifo->out)和队尾(fifo->in)之间的内存空间,而是把超出队头队尾之间长度的数据放到整个队列buffer的开始处,如图:


蓝色部分为真实数据所在内存段,白色部分其实为逻辑上假定的数据所在地,也就是说,为了给用户一种真正的队列感觉——从尾部推进数据,从头部拉取数据,那么就必须让fifo->out和fifo->in只能一直往一个方向推进,但是由于fifo所分配的buffer是有限的一段连续内存,fifo->out和fifo->in迟早要“越界”,因此,代码中是这样来处理所谓的“越界”情况的:

首先是入队列的操作,保证fifo->out和fifo->in是一直往右推进的:

unsigned int __kfifo_put(struct kfifo *fifo, 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;

}

可以明显看到,如果fifo->in小于buffer->size,那么先放完buffer->size-fifo->in这段内存空间,剩下的部分,转移到buffer的可用空间开头存放;如果fifo->in大于buffer->size,那么直接把要入队列的数据放到buffer可用空间开头。

其次是出队列的操作:

unsigned int __kfifo_get(struct kfifo *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;

}

情况1:fifo->in大于fifo->size而fifo->out小于fifo->size(即只有fifo->in“越界”),则先读取fifo->out到fifo->size-1的那一段,大小为l个byte,然后再读取剩下的从buffer开头,大小为len-l个byte的数据(如下图所示,即先读data A段, 再读出data B段);


情况2:fifo->in和fifo->out都“越界”了,那么l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); 这一语句便起作用了,此时fifo->out&fifo->size-1的结果即实际要读的数据所在的内存地址相对于buffer起始地址的偏移值(如下图所示,左边为实际上存在于内存中的data A段, 而右边虚线框为逻辑上的data A段的位置);


最后我自己有个疑问,fifo->out和fifo->in是unsign int(32bit)类型,如果应用程序在使用kfifo的时候,不断偏移,最终导致fifo->out或者fifo->in溢出,那么这种情况如何处理呢?kfifo的代码中并没有提到这种问题,等待深究。

来源:http://yiphon.diandian.com/post/2011-09-10/4918347

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值