linux内核————队列

linux内核——队列

定义:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. struct __kfifo{  
  2.     unsigned int in;  //入队偏移,写索引  
  3.     unsigned int out;  //出队偏移,读索引  
  4.     unsigned int mask;  
  5.     unsigned int esize;  
  6.     void *data;  
  7. }  


使用:

 

创建一个队列,该函数创建并初始化一个大小为size的kfifo:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 38 int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,  
  2. 39                 size_t esize, gfp_t gfp_mask)  
  3. 40 {  
  4.   
  5. 45         size = roundup_pow_of_two(size);  
  6. 46   
  7. 47         fifo->in = 0;  
  8. 48         fifo->out = 0;  
  9. 49         fifo->esize = esize;  
  10. 50   
  11. 51         if (size < 2) {  
  12. 52                 fifo->data = NULL;  
  13. 53                 fifo->mask = 0;  
  14. 54                 return -EINVAL;  
  15. 55         }  
  16. 56   
  17. 57         fifo->data = kmalloc(size * esize, gfp_mask);  
  18. 58   
  19. 59         if (!fifo->data) {  
  20. 60                 fifo->mask = 0;  
  21. 61                 return -ENOMEM;  
  22. 62         }  
  23. 63         fifo->mask = size - 1;  
  24. 64   
  25. 65         return 0;  
  26. 66 }  


判断一个整数是否是2的整数次幂

 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. static inline int is_power_of_2(unsigned long long n)  
  2. {  
  3. return (n!=0 &&(n&(n-1)==0))  
  4. }  


推入数据到队列的方法是kfifo_in()函数

 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1.  102 static void kfifo_copy_in(struct __kfifo *fifo, const void *src,  
  2. 103                 unsigned int len, unsigned int off)  
  3. 104 {  
  4. 105         unsigned int size = fifo->mask + 1;  
  5. 106         unsigned int esize = fifo->esize;  
  6. 107         unsigned int l;  
  7. 108   
  8. 109         off &= fifo->mask;  //该操作从数学角度将就是对长度fifo->mask的取模运算   
  9. 110         if (esize != 1) {  
  10. 111                 off *= esize;  
  11. 112                 size *= esize;  
  12. 113                 len *= esize;  
  13. 114         }  
  14. 115         l = min(len, size - off);  //size-off代表的含义是当前in到缓冲区尾的大小,  
  15. 116     /* 
  16.             先从buffer中拷贝l字节到缓冲区剩余空间,l<=len,也<=从real_in开始到缓冲区结尾的空间  
  17.             所以这个copy可能没拷贝完,但是不会造成缓冲区越界  
  18.         */  
  19. 117         memcpy(fifo->data + off, src, l);    
  20.         /* 
  21.             len > l时,拷贝buffer中剩余的内容,其实地址当然为buffer + l,而剩余的大小为len - l  
  22.             当len == l时,下面的memcpy啥都不干 
  23.         */  
  24. 118         memcpy(fifo->data, src + l, len - l);  
  25. 123         smp_wmb();  
  26. 124 }  
  27. 125   
  28. 126 unsigned int __kfifo_in(struct __kfifo *fifo,  
  29. 127                 const void *buf, unsigned int len)  //buf指向的是请求入队的缓冲区,len表示的是请求写入的大小  
  30. 128 {  
  31. 129         unsigned int l;  
  32. 131         l = kfifo_unused(fifo);//计算队列中剩余空间的大小,fifo->size-(fifo->in-fifo->out)  
  33. 132         if (len > l)  
  34. 133                 len = l;  
  35. 135         kfifo_copy_in(fifo, buf, len, fifo->in);  
  36. 136         fifo->in += len;  
  37. 137         return len;  
  38. 138 }  


 kfifo的巧妙之处在于in和out定义为无符号类型,在put和get时,in和out都是增加,当达到最大值时,产生溢出,使得从0开始,进行循环使用

posted on 2015-01-18 19:44  知了112  阅读(361)  评论(0编辑  收藏  举报