下面开始看初始化event_base结构的相关函数。相关源码位于event.c

event_init()

首先调用event_init()初始化event_base结构体
  1. struct event_base *
  2. event_init(void)
  3. {
  4. struct event_base *base = event_base_new(); //event_init()调用event_base_new()
  5. if (base != NULL)
  6. current_base = base;
  7. return (base);
  8. }

我们发现event_init()工作量很少,只是调用event_base_new()函数,所以真正初始化event_base的工作是在event_base_new()函数内完成。

event_base_new()

  1. struct event_base *
  2. event_base_new(void) //初始化libevent的event_base
  3. {
  4. int i;
  5. struct event_base *base;
  6. if ((base = calloc(, sizeof(struct event_base))) == NULL) //在堆上分配内存存储event_base,所有字段初始化为0
  7. event_err(, "%s: calloc", __func__);
  8. event_sigcb = NULL;
  9. event_gotsig = ;
  10. detect_monotonic(); //设置use_monotonic变量
  11. gettime(base, &base->event_tv); //base->tv_cache.tv_sec非0,则赋给base->event_tv
  12.  
  13. min_heap_ctor(&base->timeheap); //初始化定时事件的小根堆base->timeheap min_heap.h
  14. TAILQ_INIT(&base->eventqueue); //初始化注册事件链表base->eventqueue sys/queue.h
  15. base->sig.ev_signal_pair[] = -; //初始化信号base->sig
  16. base->sig.ev_signal_pair[] = -;
  17.  
  18. base->evbase = NULL; //初始化I/O多路复用 base->evbase
  19. //遍历全局数组eventops[],初始化libevent的I/O多路复用机制
  20. for (i = ; eventops[i] && !base->evbase; i++) { //以NULL标志数组结尾,只选取一个I/O多路复用机制
  21. base->evsel = eventops[i]; //初始化base->evsel
  22. base->evbase = base->evsel->init(base); //初始化base->evbase
  23. }
  24. if (base->evbase == NULL) //没有I/O多路复用
  25. event_errx(, "%s: no event mechanism available", __func__);
  26. if (evutil_getenv("EVENT_SHOW_METHOD")) //调用getenv()获取环境变量EVENT_SHOW_METHOD evutil.c
  27. event_msgx("libevent using: %s\n",
  28. base->evsel->name);
  29. /* allocate a single active event queue */
  30. //event_base_new()内调用event_base_priority_init()
  31. event_base_priority_init(base, ); //设置优先级base->nactivequeues;分配数组base->activequeues。数组大小和优先级相同
  32. return (base);
  33. }

其中由3点需要注意:

1.该函数调用calloc()在堆上分配内存来存储event_base;

2.使用全局数组eventops[]存储系统支持的I/O多路复用机制,然后遍历该数组,选取第1个I/O多路复用机制。

3.libevent支持event有优先级,所以又调用了event_base_priority_init()来完成优先级相关的设置。

event_base_priority_init()

  1. //设置不同event的优先级,值越小,优先级越高
  2. //返回值:0,成功;-1,出错
  3. int
  4. event_base_priority_init(struct event_base *base, int npriorities)
  5. {
  6. int i;
  7. if (base->event_count_active) //当前base上有活跃的events则不能设置优先级,返回。
  8. return (-);
  9. if (npriorities == base->nactivequeues) //设置的优先级和当前优先级相同,则直接返回
  10. return ();
  11. if (base->nactivequeues) { //不同,则先释放原先的activequeues数组
  12. for (i = ; i < base->nactivequeues; ++i) {
  13. free(base->activequeues[i]);
  14. }
  15. free(base->activequeues);
  16. }
  17. /* Allocate our priority queues */
  18. base->nactivequeues = npriorities; //设置新的优先级
  19. base->activequeues = (struct event_list **)
  20. calloc(base->nactivequeues, sizeof(struct event_list *)); //设置和优先级值相同大小的event_list数组
  21. if (base->activequeues == NULL)
  22. event_err(, "%s: calloc", __func__);
  23. for (i = ; i < base->nactivequeues; ++i) {
  24. base->activequeues[i] = malloc(sizeof(struct event_list)); //初始化activequeues数组中每个元素
  25. if (base->activequeues[i] == NULL)
  26. event_err(, "%s: malloc", __func__);
  27. TAILQ_INIT(base->activequeues[i]);
  28. }
  29. return ();
  30. }

该函数设置优先级,初始化了event_base的nactivequeues成员和activequeues成员。优先级值越小,优先级越高。在活跃事件链表中,优先级高的event先被处理。

Libevent源码分析—event_init()的更多相关文章

  1. 【转】libevent源码分析

    libevent源码分析 转自:http://www.cnblogs.com/hustcat/archive/2010/08/31/1814022.html 这两天没事,看了一下Memcached和l ...

  2. Libevent源码分析 (1) hello-world

    Libevent源码分析 (1) hello-world ⑨月份接触了久闻大名的libevent,当时想读读源码,可是由于事情比较多一直没有时间,现在手头的东西基本告一段落了,我准备读读libeven ...

  3. Libevent源码分析系列【转】

    转自:https://www.cnblogs.com/zxiner/p/6919021.html 1.使用libevent库     源码那么多,该怎么分析从哪分析呢?一个好的方法就是先用起来,会用了 ...

  4. Libevent源码分析系列

    1.使用libevent库     源码那么多,该怎么分析从哪分析呢?一个好的方法就是先用起来,会用了,然后去看底层相应的源码,这样比较有条理,自上向下掌握.下面用libevent库写个程序,每隔1秒 ...

  5. libevent源码分析

    这两天没事,看了一下Memcached和libevent的源码,做个小总结. 1.入门 1.1.概述Libevent是一个用于开发可扩展性网络服务器的基于事件驱动(event-driven)模型的网络 ...

  6. Libevent源码分析—event_base_dispatch()

    我们知道libevent是一个Reactor模式的事件驱动的网络库.   到目前为止,我们已经看了核心的event和event_base结构体的源码,看了初始化这两个结构体的源码,看了注册event的 ...

  7. libevent源码分析二--timeout事件响应

    libevent不仅支持io事件,同时还支持timeout事件与signal事件,这篇文件将分析libevent是如何组织timeout事件以及如何响应timeout事件. 1.  min_heap ...

  8. libevent源码分析一--io事件响应

    这篇文章将分析libevent如何组织io事件,如何捕捉事件的发生并进行相应的响应.这里不会详细分析event与event_base的细节,仅描述io事件如何存储与如何响应. 1.  select l ...

  9. Libevent源码分析—event, event_base

    event和event_base是libevent的两个核心结构体,分别是反应堆模式中的Event和Reactor.源码分别位于event.h和event-internal.h中 1.event: s ...

随机推荐

  1. ls命令的20个实用范例

    contents ls -l -h -lhS -l --block-size=M -a -d */ -g -G -n --color=never -i -p -r -R -t ls ~ ls --ve ...

  2. 事务隔离级别与传播机制,spring+mybatis+atomikos实现分布式事务管理

    1.事务的定义:事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功.其必须遵循四个原则(ACID). 原子性(Atomicity):即事务是不可分割的最小工作单 ...

  3. java多线程基本概述(三)——同步块

    1.1.synchronized方法的弊端 package commonutils; public class CommonUtils { public static long beginTime1; ...

  4. python os模块常用方法

    OS模块是Python标准库中的一个操作模块,主要用于处理Linux操作系统中的文件和目录 1.要使用OS必须先导入OS import os 2.os.getcwd()获取当前路径. print os ...

  5. finally块执行时间

    finally块在代码中什么时候被执行? 在Java语言的异常处理中,finally块的作用十九为了保证无论出现什么情况,finally块里面的代码一定会被执行.由于程序执行return就以为这结束对 ...

  6. DOM0 DOM2 DOM3

    DOM0  DOM2  DOM3 DOM是什么 W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容.结构和样式. DOM 定义了访问 HTML 和 ...

  7. Entity Framework查询注意

    首先我们看下where的方法,直接查看定义(定义如下),其实一种是对IEnumerable的扩展,一种是对IQueryable的扩展,直接看最常用的,其实区别就在IEnumerable的扩展的参数是系 ...

  8. Android SQLite与ListView的简单使用

    2017-04-25 初写博客有很多地方都有不足,希望各位大神给点建议. 回归主题,这次简单的给大家介绍一下Android SQLite与ListView的简单使用sqlite在上节中有介绍,所以在这 ...

  9. python——模块

    一.导入模块 Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入.导入模块有一下几种方法: 1 import module 2 fr ...

  10. 阿里云主机试用之自建站点和ftp上传所遇的2个问题

    1.Access to the requested object is only available from the local network 其实我并没有自建站点,只是使用了XAMPP来建了ap ...