linux kernel data struct : circular buf

  今天我们来看一下,linux kernel driver中经常使用的环形缓冲区以及对它的操作,参考文件:u_serial.c,如下图所示:

                     
                        buf_buf
                          +
                          |
                         v
           +----------x-----------+
           |                             |
           |                             |
           |       buf_get +---->|
           |                             |
           |                             |
           |                             |
           |                             |
           |                             |<------+ buf_put
           |                             |
           |                             |
           +----------------------+

     (它是圆的,它是圆的)

  它的“名”如下:
   84 /* circular buffer */
 85 struct gs_buf {
 86         unsigned                buf_size;
 87         char                    *buf_buf;
 88         char                    *buf_get;
 89         char                    *buf_put;
 90 };
 91
  其中,buf_size为缓冲区大小,buf_buf指向开辟缓冲区的起始地址,buf_get指向缓冲区中可读的起

始地址,buf_put为可写的缓冲区起始地址。

  同时,该文件还封装了对Circle buf的几个方法,如下:
 
  //实例化,开辟空间,赋初值
155 static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
156 {
157         gb->buf_buf = kmalloc(size, GFP_KERNEL);
158         if (gb->buf_buf == NULL)
159                 return -ENOMEM;
160
161         gb->buf_size = size;
162         gb->buf_put = gb->buf_buf;
163         gb->buf_get = gb->buf_buf;
164
165         return 0;
166 }


  //释放空间
173 static void gs_buf_free(struct gs_buf *gb)
174 {
175         kfree(gb->buf_buf);
176         gb->buf_buf = NULL;
177 }


  //清空可读的内容
184 static void gs_buf_clear(struct gs_buf *gb)
185 {
186         gb->buf_get = gb->buf_put;
187         /* equivalent to a get of all data available */
188 }


  //circle buf status : how many data do we have
196 static unsigned gs_buf_data_avail(struct gs_buf *gb)
197 {
198         return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
199 }


  //circle buf status : how many space left to write
207 static unsigned gs_buf_space_avail(struct gs_buf *gb)
208 {
209         return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
210 }


  //write buf
220 static unsigned
221 gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
222 {
223         unsigned len;
224
225         len  = gs_buf_space_avail(gb);
226         if (count > len)
227                 count = len;
228
229         if (count == 0)
230                 return 0;
231
232         len = gb->buf_buf + gb->buf_size - gb->buf_put;
233         if (count > len) {
234                 memcpy(gb->buf_put, buf, len);
235                 memcpy(gb->buf_buf, buf+len, count - len);
236                 gb->buf_put = gb->buf_buf + count - len;
237         } else {
238                 memcpy(gb->buf_put, buf, count);
239                 if (count < len)
240                         gb->buf_put += count;
241                 else /* count == len */
242                         gb->buf_put = gb->buf_buf;
243         }
244
245         return count;
246 }

   //read from buf
256 static unsigned
257 gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
258 {
259         unsigned len;
260
261         len = gs_buf_data_avail(gb);
262         if (count > len)
263                 count = len;
264
265         if (count == 0)
266                 return 0;
267
268         len = gb->buf_buf + gb->buf_size - gb->buf_get;
269         if (count > len) {
270                 memcpy(buf, gb->buf_get, len);
271                 memcpy(buf+len, gb->buf_buf, count - len);
272                 gb->buf_get = gb->buf_buf + count - len;
273         } else {
274                 memcpy(buf, gb->buf_get, count);
275                 if (count < len)
276                         gb->buf_get += count;
277                 else /* count == len */
278                         gb->buf_get = gb->buf_buf;
279         }
280
281         return count;
282 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值