• libevent源码分析:bufferevent


    struct bufferevent定义在文件bufferevent_struct.h中。

     1 /**
     2   Shared implementation of a bufferevent.
     3 
     4   This type is exposed only because it was exposed in previous versions,
     5   and some people's code may rely on manipulating it.  Otherwise, you
     6   should really not rely on the layout, size, or contents of this structure:
     7   it is fairly volatile, and WILL change in future versions of the code.
     8 **/
     9 struct bufferevent {
    10     /** Event base for which this bufferevent was created. */
    11     struct event_base *ev_base;
    12     /** Pointer to a table of function pointers to set up how this
    13         bufferevent behaves. */
    14     const struct bufferevent_ops *be_ops;
    15 
    16     /** A read event that triggers when a timeout has happened or a socket
    17         is ready to read data.  Only used by some subtypes of
    18         bufferevent. */
    19     struct event ev_read;
    20     /** A write event that triggers when a timeout has happened or a socket
    21         is ready to write data.  Only used by some subtypes of
    22         bufferevent. */
    23     struct event ev_write;
    24 
    25     /** An input buffer. Only the bufferevent is allowed to add data to
    26         this buffer, though the user is allowed to drain it. */
    27     struct evbuffer *input;
    28 
    29     /** An input buffer. Only the bufferevent is allowed to drain data
    30         from this buffer, though the user is allowed to add it. */
    31     struct evbuffer *output;
    32 
    33     struct event_watermark wm_read;
    34     struct event_watermark wm_write;
    35 
    36     bufferevent_data_cb readcb;
    37     bufferevent_data_cb writecb;
    38     /* This should be called 'eventcb', but renaming it would break
    39      * backward compatibility */
    40     bufferevent_event_cb errorcb;
    41     void *cbarg;
    42 
    43     struct timeval timeout_read;
    44     struct timeval timeout_write;
    45 
    46     /** Events that are currently enabled: currently EV_READ and EV_WRITE
    47         are supported. */
    48     short enabled;
    49 };

     libevent中的event结构对应套接字的某一个事件,读或者写,bufferevent结构对应一个套接字,其中有两个event结构:evread、evwrite。

    对bufferevent的操作主要有:

    1、bufferevent_socket_new,分配一个bufferevent对象并初始化,该函数内部依次调用了bufferevent_init_common_、event_assign(evread)、event_assign(evwrite),在该函数中只是初始化了读写事件,并没有调用event_add,两个事件的回调函数分别是定义在bufferevent_socket.c中的bufferevent_readcb、bufferevent_writecb,传递的参数是bufferevent指针。

    2、bufferevent_new,分配一个bufferevent对象并设置回调,该函数的实现其实是依次调用了bufferevent_socket_new和bufferevent_setcb。

    3、bufferevent_setcb,为bufferevent结构设置readcb、writecb、eventcb。

    4、bufferevent_init_common_,初始化bufferevent公共的部分成员,例如:be_ops(设置bufferevent的行为)。

    5、bufferevent_enable,使bufferevent生效(前面说过,初始化的时候并未调用event_add),该函数调用bufferevent的成员be_ops.enable,根据上面bufferevent_init_common_函数可知,enable实际调用了bufferevent_ops_socket.be_socket_enable,be_socket_enable调用了bufferevent_add_event_函数,bufferevent_add_event_函数调用了event_add。所以由此可以得知,使得evread、evwrite事件有效的函数是bufferevent_enable。

    6、bufferevent_disable,使bufferevent失效,该函数调用关系类似于bufferevent_enable,bufferevent_disable->bufferevent.be_ops->bufferevent_ops_socket.be_socket_disable->event_del。

    按照我对libevent的理解,evwrite在写完数据应该是被设置为无效的,因为正常情况下,一个套接字一直是可写的,所以写事件一直是有效的,所以需要找到bufferevent是怎么管理evread、evwrite事件的。

    bufferevent的作用就是对数据的读写做一个缓存,所以调用bufferevent_setcb函数传入的readcb、writecb、eventcb三个回调函数,其中readcb应该是读取了一些数据之后被回调的,此时数据已经被读取到了evbuffer中;而writecb应该是写入了一些数据之后被回调的,此时应该应该已经将evwrite设置为无效的了,应该在调用完send之后执行的。bufferevent封装了底层的recv和send。

    在调用bufferevent_socket_new中,调用了evbuffer_add_cb函数为output(对应输出的evbuffer)设置了相应的回调函数bufferevent_socket_outbuf_cb,在该函数中调用了bufferevent_add_event_,从上面的分析可以知道该函数会使evwrite事件生效,也就是开始监听可读事件,所以这里是使evwrite生效的地方

    在bufferevent_writecb中,可以找到当output中没有数据时,确实调用了bufferevent_disable,所以这里就是使evwrite失效的地方,由此跟我上面的推测一样。

    到这里,关于bufferevent的分析就结束了。

  • 相关阅读:
    Java使用jxl修改现有Excel文件内容,并验证其是否对公式的结果产生影响
    Java使用MyBatis的ScriptRunner执行SQL脚本
    Linux下批量解压.Z格式文件
    Java中将一个反斜杠转换成两个反斜杠
    mysql线上操作常用命令
    MySQL主从不一致修复
    slave_exec_mode参数对主从复制的影响
    ssh访问跳过RSA key"yes/no"验证
    k8s更新Pod镜像
    Go 延迟函数 defer 详解
  • 原文地址:https://www.cnblogs.com/lit10050528/p/5858032.html
Copyright © 2020-2023  润新知