• libevent学习一


    常见的异步IO存在的问题:
     
    1.使用 fcntl(fd, F_SETFL, O_NONBLOCK);,为什么在处理上效率不好。
     
        a.在没有数据可读写的时候,循环会不停执行,浪费掉大部分cpu
        b.每次尝试读写文件描述符,都会执行一次内核调用(recv,write),而系统调用耗时。
     
    2.使用select方式缺陷是什么?
        a.如果检查的文件描述符太多,每次设置和检查的耗时就会长。
     
    libevent的设计目标
    1.可移植性
    2.快速
    3.易扩展
    4.使用方便
     
    libevent的组件
     
    1.evutil
       抽象通用功能,屏蔽不同平台的实现
    2.event and event_base
       将不同平台的异步IO抽象成统一接口。在socket可读、可写时 通知应用程序,可做超时控制,在通知应用程序系统信号。
    3.bufferevent
       提供方便的缓冲读写接口
    4.evbuffer
       bufferevent的后端实现
    5.evhttp
       简单的http客户端,服务端实现
    6.evdns
       简单的dns客户端,服务端实现
    7.evrpc
       远程调用。
     
     
    库文件
    libevent_core:核心,包括了所有event_base ,evbuffer,bufferevent,和其他的通用功能
    libevent_extra:包括http,dns,rpc
    libevent:历史版本,将来会被去掉
    libevent_threads:某些平台会有,提供多线程和锁功能
    libevent_openssl:提供加解密功能
     
     
    头文件(目前所用的所有头文件都在event2目录下面)
    API headers:定义所有公用接口,没有后缀
    Compatibility headers:兼容性头文件,用于支持过时的接口
    Structure headers:用于定义易变的结构体。有些用于直接快速访问接口图,有些用于历史版本访问。任何直接依赖该头文件的程序将不具有可一致性。这类头文件带有"_struct.h"后缀
     
     
     
    libevent的配置
     
    libevent的有多种全局配置,主要通过书写和设置回调函数实现。
    主要的配置项有以下几个
    1.日志
       默认的日志以及debug信息(如果编译时打开了debug模式),将写入到stderr,但可以通过书写和替换回调函数写入到自定义文件。
       //参数和等级信息
      typedef void (*event_log_cb)(int severity, const char *msg);
      void event_set_log_callback(event_log_cb cb); //参数为NULL则丢弃日志
        
     
    2.处理重大错误,默认退出程序(exit() or abort() )
       
    typedef void (*event_fatal_cb)(int err);
    void event_set_fatal_callback(event_fatal_cb cb);
      
     自定义函数不应该再使用任何libevent接口,否则会导致未定义行为。
     
    3.内存管理
    void event_set_mem_functions(void *(*malloc_fn)(size_t sz),
                                 void *(*realloc_fn)(void *ptr, size_t sz),
                                 void (*free_fn)(void *ptr));
     
    自定义函数需要注意对齐,需要和c内存分配相同的对齐方式
    还需要注意调用时机,需要在所有内存分配之前
     
    4.锁和多线程
       libevent与多线程的工作模式
       a.固有单线程,不安全
       b.可选锁模式,需要为每个会被用在多线程场景下的对象进行说明。
       c.始终锁模式,总是线程安全。
     
        可自定义锁函数,并设置,设置必须发生在libevent分配任何共享结构之前
     
       
    define EVTHREAD_WRITE  0x04
    #define EVTHREAD_READ   0x08
    #define EVTHREAD_TRY    0x10

    #define EVTHREAD_LOCKTYPE_RECURSIVE 1
    #define EVTHREAD_LOCKTYPE_READWRITE 2

    #define EVTHREAD_LOCK_API_VERSION 1

    struct evthread_lock_callbacks {
           int lock_api_version;
           unsigned supported_locktypes;
           void *(*alloc)(unsigned locktype);
           void (*free)(void *lock, unsigned locktype);
           int (*lock)(unsigned mode, void *lock);
           int (*unlock)(unsigned mode, void *lock);
    };

    int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);

    void evthread_set_id_callback(unsigned long (*id_fn)(void));

    struct evthread_condition_callbacks {
            int condition_api_version;
            void *(*alloc_condition)(unsigned condtype);
            void (*free_condition)(void *cond);
            int (*signal_condition)(void *cond, int broadcast);
            int (*wait_condition)(void *cond, void *lock,
                const struct timeval *timeout);
    };

    int evthread_set_condition_callbacks(
            const struct evthread_condition_callbacks *);
     
     
    5.调试锁的用法(可以探测“未锁”,“重复锁”等典型错误)
    void evthread_enable_lock_debugging(void);
    #define evthread_enable_lock_debuging() evthread_enable_lock_debugging()
     
     
    6.调试事件用法(可以探测事件是否未初始化,或者重复初始化等问题)
    void event_enable_debug_mode(void);
    void event_debug_unassign(struct event *ev);
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Eclipse在线安装spring-tool-suit插件
    使用Eclipse构建Maven项目
    uwsgi+flask环境中安装matplotlib
    开启flask调试
    linux进入软连接所指向的原目录
    eclipse打不开,报错 "java was started with exit code=13"
    gnuplot 的安装
    使用tcp_probe时最初没有输出,先卸载后加载模块之后就有了。
    一个简单的socket程序运行与抓包查看
    如何查看文件是dos格式还是unix格式的?
  • 原文地址:https://www.cnblogs.com/manziluo/p/5789624.html
Copyright © 2020-2023  润新知