libevent源码解析(四)evbuffer结构

一.前言

  在前文中,我们分析了libevent库最基本的事件:event的数据结构及相关接口函数,并分析了event背后(backend)的事件库/事件管理核心event_base的数据结构及相关接口函数,由此了解了事件管理的整个循环过程,以及加入、删除、激活、释放事件等基本操作。在此基础上,本文分析缓冲部分,即evbuffer结构。

二.evbuffer结构体

  话不多数,直接看源码部分:

struct evbuffer {
    /*使用evbuffer_chain存储缓冲:链表形式的多个缓冲区*/
    /** The first chain in this buffer's linked list of chains. */
    struct evbuffer_chain *first;
    /** The last chain in this buffer's linked list of chains. */
    struct evbuffer_chain *last;

    /** Pointer to the next pointer pointing at the 'last_with_data' chain.
     * 该指针指向最后一个有数据的evbuffer_chain结构体
     * To unpack:
     *
     * The last_with_data chain is the last chain that has any data in it.
     * If all chains in the buffer are empty, it is the first chain.
     * If the buffer has no chains, it is NULL.
     *
     * The last_with_datap pointer points at _whatever 'next' pointer_
     * pointing at the last_with_data chain. If the last_with_data chain
     * is the first chain, or it is NULL, then the last_with_datap pointer
     * is &buf->first.
     */
    struct evbuffer_chain **last_with_datap;


    /** 存储总数据 Total amount of bytes stored in all chains.*/
    size_t total_len;

    /** 自上次回调以来增加的buffer 
     *  Number of bytes we have added to the buffer since we last tried to
     *  invoke callbacks. */
    size_t n_add_for_cb;

    /** 自上次回调以来清空的buffer 
     *  Number of bytes we have removed from the buffer since we last
     *  tried to invoke callbacks. */
    size_t n_del_for_cb;

    /*多线程下保证线程安全的锁*/
#ifndef EVENT__DISABLE_THREAD_SUPPORT
    /** A lock used to mediate access to this buffer. */
    void *lock;
#endif

    /* 标记位,分别作用于:
     * 1. 释放缓冲时是否解锁
     * 2. 是否允许缓冲区头、尾部的更改
     * 3. 是否在改变缓冲区时立刻相应回调函数
     */
    /** True iff we should free the lock field when we free this
     * evbuffer. */
    unsigned own_lock : 1;
    /** True iff we should not allow changes to the front of the buffer
     * (drains or prepends). */
    unsigned freeze_start : 1;
    /** True iff we should not allow changes to the end of the buffer
     * (appends) */
    unsigned freeze_end : 1;
    /** True iff this evbuffer's callbacks are not invoked immediately
     * upon a change in the buffer, but instead are deferred to be invoked
     * from the event_base's loop.  Useful for preventing enormous stack
     * overflows when we have mutually recursive callbacks, and for
     * serializing callbacks in a single thread. */
    unsigned deferred_cbs : 1;


    /*用于IOCP的IO复用标记位*/
#ifdef _WIN32
    /** True iff this buffer is set up for overlapped IO. */
    unsigned is_overlapped : 1;
#endif

    /** Zero or more EVBUFFER_FLAG_* bits */
    ev_uint32_t flags;

    /** 对应于标记位回调函数不立刻响应 Used to implement deferred callbacks. */
    struct event_base *cb_queue;

    /** 标记位,为0的时候清空bufffer 
     *  A reference count on this evbuffer.  When the reference count
     *  reaches 0, the buffer is destroyed. Manipulated with
     *  evbuffer_incref and evbuffer_decref_and_unlock and
     *  evbuffer_free. */
    int refcnt;

    /** 回调函数 A struct event_callback handle to make all of this buffer's callbacks
     *  invoked from the event loop. */
    struct event_callback deferred;

    /** A doubly-linked-list of callback functions */
    LIST_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;

    /** 涉及到bufferevent 结构体,后文详谈
     *  The parent bufferevent object this evbuffer belongs to.
     *  NULL if the evbuffer stands alone. */
    struct bufferevent *parent;
};

  从源码中可以很清楚的看出,libevent的buffer区域并非申请一整块连续空间,而是用一个链表evbuffer_chain的形式存储多个区域,构成了整个evbuffer。这种存储方式的优点在于便于动态增加、减少缓冲区的大小,实现了一个类似于C++的动态数组的容器。

三.evbuffer_chain结构体

  evbuffer_chain链表源码如下:

/** 缓冲区链表结构 A single item in an evbuffer. */
struct evbuffer_chain {
    /** points to next buffer in the chain */
    struct evbuffer_chain *next;

    /** 缓冲区长度 total allocation available in the buffer field. */
    size_t buffer_len;

    /** 缓冲区空闲区域:用于发送buffer
     * unused space at the beginning of buffer or an offset into a
     * file for sendfile buffers. */
    ev_misalign_t misalign;

    /** 偏移量 Offset into buffer + misalign at which to start writing.
     * In other words, the total number of bytes actually stored
     * in buffer. */
    size_t off;

    /** 标记位:Set if special handling is required for this chain */
    unsigned flags;
#define EVBUFFER_FILESEGMENT    0x0001  /**< A chain used for a file segment */
#define EVBUFFER_SENDFILE   0x0002  /**< a chain used with sendfile */
#define EVBUFFER_REFERENCE  0x0004  /**< a chain with a mem reference */
#define EVBUFFER_IMMUTABLE  0x0008  /**< read-only chain */
    /** a chain that mustn't be reallocated or freed, or have its contents
     * memmoved, until the chain is un-pinned. */
#define EVBUFFER_MEM_PINNED_R   0x0010
#define EVBUFFER_MEM_PINNED_W   0x0020
#define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W)
    /** a chain that should be freed, but can't be freed until it is
     * un-pinned. */
#define EVBUFFER_DANGLING   0x0040
    /** a chain that is a referenced copy of another chain */
#define EVBUFFER_MULTICAST  0x0080

    /** 对应于evbuffer中同名变量 number of references to this chain */
    int refcnt;

    /** 真正的缓冲区 Usually points to the read-write memory belonging to this
     * buffer allocated as part of the evbuffer_chain allocation.
     * For mmap, this can be a read-only buffer and
     * EVBUFFER_IMMUTABLE will be set in flags.  For sendfile, it
     * may point to NULL.
     */
    unsigned char *buffer;
};

四.小结

  本文分析了evbuffer和evbuffer_chain数据结构,和前文event以及event_base一样,evbuffer也有对应的接口函数,在下文中将进行源码的分析和功能的介绍。

猜你喜欢

转载自blog.csdn.net/u013354486/article/details/80813456