Chinaunix首页 | 论坛 | 博客
  • 博客访问: 550667
  • 博文数量: 469
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 1495
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-15 21:04
文章分类

全部博文(469)

文章存档

2015年(81)

2014年(125)

2013年(261)

2012年(2)

分类: LINUX

2013-08-27 11:34:29

转自:http://zhyclt.blog.163.com/blog/static/839359200881210747973/

Author : Kevin Lynx

前言

    可以说对于任何网络库(模块)而言,一个缓冲模块都是必不可少的。缓冲模块主要用于缓冲从网络接收到的数据,以及
用户提交的数据(用于发送)。很多时候,我们还需要将网络模块层(非TCP层)的这些缓冲数据拷贝到用户层,而这些内存拷贝
都会消耗时间。
    在这里,我简要分析下libevent的相关代码(event.h和buffer.c)。

结构

    关于libevent的缓冲模块,主要就是围绕evbuffer结构体展开。先看下evbuffer的定义:

libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游/*event.h*/
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游struct evbuffer {
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    u_char *buffer;
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    u_char *orig_buffer; 
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    size_t misalign;
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    size_t totallen;
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    size_t off; 
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    void (*cb)(struct evbuffer *, size_t, size_t, void *);
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游    void *cbarg;
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游};
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游
libevent 源码分析:evbuffer缓冲(附带libevent vs2005完整包下载) - 虾虾水中游 - 虾虾水中游


    libevent的缓冲是一个连续的内存区域,其处理数据的方式(写数据和读数据)更像一个队列操作方式:从后写入,从前
读出。evbuffer分别设置相关指针(一个指标)用于指示读出位置和写入位置。其大致结构如图:

evbuffer_str 
    orig_buffer指向由realloc分配的连续内存区域,buffer指向有效数据的内存区域,totallen表示orig_buffer指向的内存
区域的大小,misalign表示buffer相对于orig_buffer的偏移,off表示有效数据的长度。

实际运作

    这里我将结合具体的代码分析libevent是如何操作上面那个队列式的evbuffer的,先看一些辅助函数:

evbuffer_drain:
    该函数主要操作一些指标,当每次从evbuffer里读取数据时,libevent便会将buffer指针后移,同时增大misalign,减小off,
而该函数正是做这件事的。说白了,该函数就是用于调整缓冲队列的前向指标。

evbuffer_expand:
    该函数用于扩充evbuffer的容量。每次向evbuffer写数据时,都是将数据写到buffer+off后,buffer到buffer+off之间已被
使用,保存的是有效数据,而orig_buffer和buffer之间则是因为读取数据移动指标而形成的无效区域。
    evbuffer_expand的扩充策略在于,首先判断如果让出orig_buffer和buffer之间的空闲区域是否可以容纳添加的数据,如果
可以,则移动buffer和buffer+off之间的数据到orig_buffer和orig_buffer+off之间(有可能发生内存重叠,所以这里移动调用的
是memmove),然后把新的数据拷贝到orig_buffer+off之后;如果不可以容纳,那么重新分配更大的空间(realloc),同样会移动
数据。
    扩充内存的策略为:确保新的内存区域最小尺寸为256,且以乘以2的方式逐步扩大(256、512、1024、...)。

    了解了以上两个函数,看其他函数就比较简单了。可以看看具体的读数据和写数据:

evbuffer_add:
    该函数用于添加一段用户数据到evbuffer中。很简单,就是先判断是否有足够的空闲内存,如果没有则调用evbuffer_expand
扩充之,然后直接memcpy,更新off指标。

evbuffer_remove:
    该函数用于将evbuffer中的数据复制给用户空间(读数据)。简单地将数据memcpy,然后调用evbuffer_drain移动相关指标。

阅读(778) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~