• Libevent源码剖析(二)之数据结构


    描述Libevent中出现的数据结构:

    struct event_base :

    事件处理集合

    struct event_base {
    	const struct eventop *evsel;        //对struct event对象的操作函数,以指针函数的方式提供
    	void *evbase;        //指向特定数据的指针
    	struct event_changelist changelist;        //记录事件变化的列表,仅由O(1)方式使用
    
    	const struct eventop *evsigsel;        //对struct event signal对象的处理,以指针函数的方式进行注册
    	struct evsig_info sig;        //实现通用信号处理程序的代码
    
    	int virtual_event_count;        //虚拟事件数量
    	int virtual_event_count_max;        //最大的活动虚拟事件数量
    	int event_count;        //添加到struct event_base中的事件总数
    	int event_count_max;        //允许添加到struct event_base中的最大的事件数量
    	int event_count_active;        //目前活动的事件总数
    	int event_count_active_max;        //允许的活动事件总数
    
    	int event_gotterm;        //标志:是否需要在事件处理结束后终止事件循环
    	int event_break;           //标志:是否应该立即终止循环
    	int event_continue;       //标志:是否应该立即启动一个新的事件循环
    	int event_running_priority;        //当前正在运行的事件的优先级
    	int running_loop;        //标志:是否运行event_base_loop函数,以防止可重入调用
    	int n_deferreds_queued;        //标志:防止饥饿的手段
    
            #define TAILQ_HEAD(name, type)			
            struct name {					
    	        struct type *tqh_first;			
    	        struct type **tqh_last;			
            }
            //活动事件管理
    	struct evcallback_list *activequeues;        //活动事件队列,so,evcallback_list很可能是使用了这种方式进行注册的
    	int nactivequeues;        //活动事件队列的长度
    	struct evcallback_list active_later_queue;        //下一次应该激活的事件队列
    
            //超时处理
    	struct common_timeout_list **common_timeout_queues;        //常用的超时队列
    	int n_common_timeouts;        //超时队列中的条目数
    	int n_common_timeouts_allocated;        //超时队列占用的总大小
    
            //管理IO事件与信号事件,我就纳闷了,用红黑树管理不好吗?
    	struct event_io_map io;        //从IO映射中添加的事件  
    	struct event_signal_map sigmap;        //从信号映射中添加的事件
    	
            struct min_heap timeheap;        //使用最小堆将超时事件组织起来
    	struct timeval tv_cache;        //缓存系统时间,避免频繁的系统调用(gettimeofday,虽然说这个函数不陷入系统调用)
    	struct evutil_monotonic_timer monotonic_timer;        //一个空的结构体,用途不明
    	struct timeval tv_clock_diff;        //时钟差异(10ms?20ms?)
    	time_t last_updated_clock_diff;        //最后一次更新事件的记录
    
    	//多线程管理
    	unsigned long th_owner_id;        //当前运行loop的thread id
    	void *th_base_lock;        //线程锁,防止对event_base的访问冲突
    	void *current_event_cond;        //条件变量,用于同步事件处理
    	int current_event_waiters;        //阻塞在当前条件变量上的等待线程
    	struct event_callback *current_event;        //正在执行的回调事件
    
    	enum event_base_config_flag flags;        //这个event_base的配置标志
    
    	struct timeval max_dispatch_time;        //一次事件循环的最大时间
    	int max_dispatch_callbacks;        //一次事件循环中可以处理的最大 的回调函数
    	int limit_callbacks_after_prio;        //回调函数中的优先级限制
            
            //通知主线程唤醒休息的线程
    	int is_notify_pending;        //标志:struct event_base是否有等待处理的通知
    	evutil_socket_t th_notify_fd[2];        //与主线程使用管道来进行交互,一般而言,会将主线程阻塞在read fd上
    	struct event th_notify;        //使用事件处理的机制通知主线程,真的是:万物皆事件哇
    	int (*th_notify_fn)(struct event_base *base);        //用于从子线程中唤醒主线程的回调函数
    
    	struct evutil_weakrand_state weakrand_seed;        //随机数种子
    	LIST_HEAD(once_event_list, event_once) once_events;        //保存目前尚未触发的通过event_once注册的事件
    };
    

    struct event

    表示一个具体的事件对象,将IO,超时,信号三者统一起来

    struct event {
    	struct event_callback ev_evcallback;        //保存事件处理的回调函数,由必要的时候对这个事件进行填充,添加到合适的优先级队列
    
            //管理超时
    	union {
    		TAILQ_ENTRY(event) ev_next_with_common_timeout;        //我觉着这个有点复杂...直接标记在最小堆中的位置,岂不方便??
    		int min_heap_idx;
    	} ev_timeout_pos;
    	evutil_socket_t ev_fd;        //关注的socket fd(int)
    	struct event_base *ev_base;        //依赖的struct event_base对象
    
    	union {
    		struct {
    			LIST_ENTRY (event) ev_io_next;        //在IO事件队列中的位置
    			struct timeval ev_timeout;
    		} ev_io;        //用于管理IO事件
    
    		struct {
    			LIST_ENTRY (event) ev_signal_next;        //在信号事件队列中的位置
    			short ev_ncalls;        
    			short *ev_pncalls;        //允许在回调中删除
    		} ev_signal;        //用于管理超时事件
    	} ev_;
    
    	short ev_events;        //关注的事件
    	short ev_res;		   //实际发生的事件 
    	struct timeval ev_timeout;            //超时时间
    };
    

    struct eventop

    struct event_base的操作

    struct eventop {
    	const char *name;        //这个后端的名称
    	void *(*init)(struct event_base *);        //初始化struct event_base对象
    	int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);        //将struct event对象添加到struct event_base对象中
    	int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);        //将struct event对象从struct event_base中移除
    	int (*dispatch)(struct event_base *, struct timeval *);        //将控制权提交给事件控制函数
    	void (*dealloc)(struct event_base *);        //清理struct event_base中的对象
    	int need_reinit;        //标志:是否需要在调用fork()函数后重新初始化事件库
    	enum event_method_feature features;        //提供可以支持struct event_method_feature位数组的
    	size_t fdinfo_len;        //为每一个fd维护的信息的长度
    };
    
    

    struct event_changelist

    事件变化的列表,仅由O(1)方法使用

    struct event_changelist {
    	struct event_change *changes;        //链表
    	int n_changes;        
    	int changes_size;
    };
    

    struct event_change

    struct event_change {
    	evutil_socket_t fd;        //Libevent对socketfd,signal,timer的封装,(int)
    	short old_events;        //fd之前上启用的事件
    
    	ev_uint8_t read_change;    //此次改变发生的读事件
    	ev_uint8_t write_change;    //此次改变发生的写事件
    	ev_uint8_t close_change;    //此次改变发生的关闭事件
    };
    

    struct event_method_feature

    enum event_method_feature {
        EV_FEATURE_ET = 0x01,
        EV_FEATURE_O1 = 0x02,
        EV_FEATURE_FDS = 0x04,
        EV_FEATURE_EARLY_CLOSE = 0x08
    };
    
    

    struct evsig_info

    为信号处理函数提供事件

    struct evsig_info {
    	struct event ev_signal;        //为信号事件注册的一个struct event对象
    	evutil_socket_t ev_signal_pair[2];        //使用进程间管道的方式处理信号事件
    	int ev_signal_added;        //判断信号事件是否已经被添加
    	int ev_n_signals_added;        //我们目前正在关注的信号数量
    	struct sigaction **sh_old;        //保存一系列信号处理对象
    	int sh_old_max;        //保存的信号处理对象的个数
    }
    

    struct common_timeout_list

    处理超时事件

    struct common_timeout_list {
    	struct event_list events;        //当前队列中正在等待的事件列表
    	struct timeval duration;        //表示事件的持续时间
    	struct event timeout_event;        //每个队列都为超时时间准备了一个struct event对象
    	struct event_base *base;        //这个struct event对象占用的
    };
    

    struct event_io_map

    #define event_io_map event_signal_map
    struct event_signal_map {
    	void **entries;        //一个二维数据,数组中会维护一些信息
    	int nentries;        //数组中的条目总数
    };
    

    struct event_callback

    回调函数的封装

    #ifndef TAILQ_ENTRY
    #define EVENT_DEFINED_TQENTRY_
    #define TAILQ_ENTRY(type)						
    struct {								
    	struct type *tqe_next;	/* next element */			
    	struct type **tqe_prev;	/* address of previous next element */	
    }
    #endif 
    
    struct event_callback {
    	TAILQ_ENTRY(event_callback) evcb_active_next;        //回调事件队列中的一个成员
    	short evcb_flags;    //根据flag选择合适的回调函数进行处理
    	ev_uint8_t evcb_pri;	//标志这个事件的优先级
    	ev_uint8_t evcb_closure;        
            union {
    		void (*evcb_callback)(evutil_socket_t, short, void *);
    		void (*evcb_selfcb)(struct event_callback *, void *);
    		void (*evcb_evfinalize)(struct event *, void *);
    		void (*evcb_cbfinalize)(struct event_callback *, void *);
    	} evcb_cb_union;        //具体的回调函数
    	void *evcb_arg;        //回调函数使用的参数
    };
    

    struct event_config

    为struct event_base提供配置对象

    #define TAILQ_HEAD(name, type)			
    struct name {					
    	struct type *tqh_first;			
    	struct type **tqh_last;			
    }
    
    struct event_config {
    	TAILQ_HEAD(event_configq, event_config_entry) entries;        //双向链表
    
    	int n_cpus_hint;        //cpus数量
    	struct timeval max_dispatch_interval;        //最大的循环时间
    	int max_dispatch_callbacks;        //最多的callbacks的调用
    	int limit_callbacks_after_prio;        //优先级限制
    	enum event_method_feature require_features;        //目前struct event_base支持的一些方法
    	enum event_base_config_flag flags;
    };
    
    

    全局数据结构:eventops

    static const struct eventop *eventops[] = {
    #ifdef EVENT__HAVE_EVENT_PORTS
    	&evportops,
    #endif
    #ifdef EVENT__HAVE_WORKING_KQUEUE
    	&kqops,
    #endif
    #ifdef EVENT__HAVE_EPOLL
    	&epollops,
    #endif
    #ifdef EVENT__HAVE_DEVPOLL
    	&devpollops,
    #endif
    #ifdef EVENT__HAVE_POLL
    	&pollops,
    #endif
    #ifdef EVENT__HAVE_SELECT
    	&selectops,
    #endif
    #ifdef _WIN32
    	&win32ops,
    #endif
    	NULL
    };
    
  • 相关阅读:
    trident介绍
    Effective TensorFlow Chapter 4: TensorFlow中的广播Broadcast机制【转】
    tslib移植笔记(1)【转】
    jz2440-linux3.4.2-kernel移植【学习笔记】【原创】
    Linxu内核版本号后面多出字符串或者+号【学习笔记】
    向linux内核版本号添加字符/为何有时会自动添加"+"号或者"xxx-dirty"【转】
    chrome浏览器新建标签打开页面【学习笔记】
    jz2440-uboot-201204版本移植【学习笔记】【原创】
    Ubuntu 14.04 下安装 TFTP 艰辛之路【转】
    更改UBoot实现通过loady命令下载代码【转】
  • 原文地址:https://www.cnblogs.com/ukernel/p/9191077.html
Copyright © 2020-2023  润新知