深入浅出libevent的使用(一)

导语:
对libevent源码分析的文章已经很多,在此不在重述原理,但从另外一个角度讲,知晓原理就是为了更好的使用libevent,本文通过介绍libevent中的mini-heap,socketpair以及对evbuffer的使用,展示libevent所依赖的几个基本数据结构

1. min-heap的使用

理解小根堆的原理和使用,对超时事件的理解比较有帮助,min-heap俗称小根堆,就是一个完全二叉树,根结点的数据比左节点大,比右节点也大,类似
这里写图片描述
在libevent中作为对超时事件的时间进行排序,根结点的时间最先超时这么个原理

  • min-heap根结点的初始化:min_heap_ctor
  • 删除根节点: min_heap_dtor
  • min-heap的插入: min_heap_push
  • min-heap的删除: min_heap_pop

示例如下:

    min_heap_ctor(&heap);
    for(i = 0;i < 9; ++i) {
        inserted[i] = mm_malloc(sizeof(struct event));
        set_random_timeout(inserted[i]);
        min_heap_push(&heap,inserted[i]);
    }

    min_heap_print(&heap);
    printf("heap size :%d\n",min_heap_size(&heap)); 
    while(1) {
        e = min_heap_pop(&heap);
        if(!e)
            break;
        mm_free(e);
    }
    min_heap_dtor(&heap);
2. socketpair的使用

socketpair的使用场景,主要是在进程间的通信,或者线程间的通信,其原理在源码分析中已经分析的相当透彻,在libevent中的使用,主要是用来在子线程中有可读事件,可写事件,通知主线程,在使用场景中的其他用途,你完全可以发挥想象,socketpair实际上就是两个本地的套接字,在一个进程中监听读,在另外一个进程中写

  • 创建socketpair的方法: evutil_socketpair

示例如下:

 ret = evutil_socketpair(LOCAL_SOCKETPAIR_AF,SOCK_STREAM,0,fds);
    if( ret < 0 ) {
        printf("evutil_socketpair falt %d!",ret);
        return -1;
    }

    if( fork() ) {
        //parent process
        int count = 0;
        int val;
        close(fds[1]);
        while(1){
            ++count;
            write(fds[0],&count,sizeof count);
            read(fds[0],&val,sizeof val);
            printf("recv data :%d\n",val);
        }
    }else{
        //child process
        int val;
        close(fds[0]);
        while(1){
            sleep(1);
            read(fds[1],&val,sizeof(val));
            printf("recv data :%d\n",val);
            val = -val;
            write(fds[1],&val,sizeof val);
        }
    }
3. evbuffer的使用

evbuffer的作用顾名思义就是读写的缓冲区,这部分实现的好坏,实际上关乎一个网络组件的效率高低,所以evbuffer的实现,还是需要花时间去理解,不过使用起来还是蛮简单的,大部分的接口,可以参考event2/buffer.h,这里需要注意的是,当evbuffer在多线程环境下使用时首先要显式调用evthread_use_pthreads函数,并且要调用 evbuffer_enable_locking来初始化evbuffer中的锁,另外需要注意evbuffer是用链表形式实现的,一个节点写入数据会有空闲块,这个空闲块小于一定的阈值时,将创建写节点来写入数据,当节点数据很小时,会创建一个新节点,来容纳这个节点数据和新写入的数据

  • evbuffer_new 创建evbuffer
  • evbuffer_add 往evbuffer中添加数据
  • evbuffer_remove 从evbuffer中拷贝数据并删除
  • evbuffer_drain 直接删除数据

示例代码:


    //写进程
    while(1) {

        sprintf(message,message_s,++count);

        message_len = strlen(message);
        //写入数据 \n结尾 
        evbuffer_add(buf,message,message_len);
        length = evbuffer_get_length(buf);
        printf("thread write :%d\n",length);
        total += message_len;
        sleep(1);
    }

    //读进程
    read_message = evbuffer_readln(buf,&read_message_len,EVBUFFER_EOL_CRLF);
    if (NULL != read_message) {
         printf("thread read :%s\n",read_message);
         length += read_message_len;
    }

完整参考:https://github.com/dengwenyi88/test_libevent/

结论:读者也可以在示例中使用更多的接口,加深使用libevent的理解,同时对源码实现的基本原理的理解有帮助,bufferevent的工作流程是依赖于,对event和event_base的进一步封装,在对套接字的读超时和写超时处理,就用到事件的超时处理,同时对socket的读监听事件和写监听事件,都涉及到event_base的基本原理,以及evbuffer中事件的回调处理

参考:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值