`
luozhaoyu
  • 浏览: 347717 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

libevent0.1&0.2源码理解(二)主要函数

阅读更多
修改记录:
3-29 初稿

介绍完类型与变量之后,就可以开始看程序的主轴了。我们从使用event-test.c入手可以看到的是:(略去之前创建命名管道和socket)
	/* Initalize the event library */
	event_init();

	/* Initalize one event */
	event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);

	/* Add it to the active events, without a timeout */
	event_add(&evfifo, NULL);
	
	event_dispatch();


首先是event_init进行了全体初始化。
在0.1中这个函数很简单,就是把之前的四个全局队列头结点置空。
在0.2中,除了初始化队列之外,选择第一个系统支持的函数处理程序,其顺序是kqueue, event_ports, epoll, poll, select(存疑。没去看现在的顺序是怎样,但肯定不是随机选择的)
在找到了合适的程序支持,比如发现了select函数可以使用之后,把select的结构体selectop的地址传给evbase。selectop的结构体是
struct selectop {
	int event_fds;		/* fd_set最大值 */
	int event_fdsz; //fd_set的大小
	fd_set *event_readset;
	fd_set *event_writeset;
} sop;


其次是用event_set初始化一个事件
event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);

这一步也很简单,其实就是把socket以及事件、标志通通给结构体evfifo赋值,没有其它东西。

再次是用event_add给之前初始化的事件配置定时器
第一步先看event_add之时传入的时间是否为空,如果不为空的话已现在的时间为准,并加上传入的时间作为结束时间。
第二步是看event中的标志是否是EVLIST_TIMEOUT,如果是EVLIST_TIMEOUT则先从timequeue中移除此事件,这个标志
第三步是从头遍历timequeue,按照从近到远的顺序找到event该被插入的位置。
第四步是给event挂上EVLIST_TIMEOUT的标志
第五步是判断libevent是否正在循环中,如果在而且标志了EVLIST_ADD,则返回;否则插进addqueue队尾,并标志EVLIST_ADD。可以看出EVLIST_ADD表明此event是否已经added进addqueue。我们可以把addqueue理解成待处理事件。如果不在循环中,则调用event_add_post(ev)——
在0.1中,事件被插入队列后会被标记上EVLIST_READ或者EVLIST_WRITE;
而在0.2中,readqueue和writequeue被合并成了eventqueue,并统一标记为EVLIST_INSERTED

注:LOG_DBG是log.h中的一个宏,用于记录日志

最后是进入处理循环event_dispatch
//这个是0.2版本的处理循环
	      while (1) {
		timeout_next(&tv);

		event_inloop = 1;
		res = evsel->dispatch(evbase, &tv);
		event_inloop = 0;

		if (res == -1)
			return (-1);

		maxfd = 0;
		for (ev = TAILQ_FIRST(&addqueue); ev; 
		     ev = TAILQ_FIRST(&addqueue)) {
			TAILQ_REMOVE(&addqueue, ev, ev_add_next);
			ev->ev_flags &= ~EVLIST_ADD;
			
			event_add_post(ev);

			if (ev->ev_fd > maxfd)
				maxfd = ev->ev_fd;
		}

		if (evsel->recalc(evbase, maxfd) == -1)
			return (-1);

		timeout_process();
	}


dispatch是重中之重,里面进行的操作如下
  • 重新计算fd_set也就是readset或者sop->event_readset变量所需要的空间大小,并把fd_set清零。
  • 把readqueue与writequeue中的所有事件的套接字放入fd_set中。
  • 从timequeue队列中取出第一个定时器到时时间tv。在tv时间之前select读写的fd_set
  • 锁上循环区(event_inloop=1),一一取readqueue或eventqueue的事件,先把这些事件从所有队列中移除之后,在一一调用各事件的回调函数即fifo_read。传入fifo_read的参数包括该事件的指针。fifo_read中再次调用event_set把event加入队列中,下次循环便会继续监听此事件。
  • 解锁循环区(event_inloop=0),把addqueue中的event全部取出来,放进readqueue或者0.2版本中的eventqueue
  • 调用recalc重新计算fd_set,也就是2中的步骤
  • 最后,对照当前时间,把timequeue队列中还没有超时的事件取出来调用回调函数。

注:0.1和0.2版本的处理顺序有所不同(在进入循环区前后所调用的东西不同。0.1是select之后再循环,0.2反之),但基本上一致

至此除event_pending外的主要函数全部介绍完毕(event_pending主要用来检查某个事件是否已被标记在计划中)

总结:
libevent0.x主要使用了Tail Queue这一数据结构存放系统各种待处理的事件队列。(现在觉得这种类型蛮奇葩的,用双向链表应该也是可以,不知Niels当初有何考量)其中一个事件(event)包含了对应的套接字和当时队列中下一个事件的指针。
每次在回调之后,都需要重新把事件加入到队列中,这是因为每次select的对象都是队列。
在0.1的一个循环中,程序先处理readqueue再处理writequeue。在0.2中,libevent把read和write一视同仁,都合并成了eventqueue
0
0
分享到:
评论

相关推荐

    libevent源码深度剖析pdf

    为方便阅读,把blog上的libevent源码深度剖析系列文章整合成一个pdf。

    libevent源码分析

    本文将对libevent源码进行分析,深入理解其实现原理以及关键的数据结构和函数接口。我们首先从libevent源码的整体架构开始,然后详细介绍一些重要的组件和它们的实现方式。 1. 开篇 在分析libevent源码之前,有必要...

    libevent源码深度剖析.zip_libevent 原理_libevent原理_libevent源码_libevent编程_

    libevent的原理和源码分析对于深入理解网络编程的底层机制至关重要。 首先,libevent的核心是其事件模型。它基于事件驱动编程模型,这种模型能够高效地处理大量并发连接。当有事件发生时,libevent会调用相应的回调...

    libevent v0.1

    在“libevent v0.1”中,主要包含以下关键知识点: 1. **事件基类(Event Base)**:每个libevent实例都有一个事件基类,它是所有事件处理的入口点。开发者可以通过它来注册事件、调度事件循环和取消事件。 2. **...

    Libevent源码分析 pdf文档 带目录

    在深入Libevent源码分析之前,需要了解它的核心概念,主要包括事件循环、事件处理器、IO事件、定时器事件、信号事件等。事件循环是Libevent的中枢,它在后台运行,检测事件源的变化,并触发相应的事件处理器。事件...

    Libevent源码解析.pdf

    Libevent 源码解析 Libevent 是一个高性能的事件驱动库,广泛应用于网络编程和高性能服务器开发中。下面是对 Libevent 源码的深入剖析,涵盖了其架构设计、事件处理机制、Reactor 模式、事件循环、IO multiplexing...

    libevent 参考手册中文版及源码解析

    6. **源码解析**:深入阅读libevent的源码,可以理解其内部实现细节,如事件调度算法、多线程支持和异步I/O处理等。 7. **性能优化**:libevent提供了很多配置选项来优化性能,例如选择合适的事件模型、使用多线程...

    libevent-1.0c 源码(资料中转)

    libevent-1.0c.tar.gz [GPG Sig] - Release 2005-04-03 Bug fixes for Windows, Solaris and improved logging interface. libevent-1.0b.tar.gz [GPG Sig] - Release ...libevent-0.1.tar.gz - Release 2000-11-14

    libevent-1.0b源码(资料中转)

    《深入解析libevent-1.0b:多线程网络通信库的...通过理解和掌握libevent的源码,开发者能够构建出更高效、可靠的网络服务。无论是对初学者还是经验丰富的程序员,libevent都是一个值得深入学习和研究的优秀开源项目。

    libevent源码

    通过深入理解和使用libevent源码,开发者可以更好地定制自己的网络应用,实现高效、稳定的服务。 总结,libevent是一个强大的工具,它提供了事件驱动的编程模型,适用于处理大量并发连接。通过理解并熟练运用...

    libevent源码深度剖析 + libevent参考手册(中文版)

    libevent库,文字版,很清晰,附带libevent参考手册(中文版) libevent源码深度剖析,根据libevent开源代码框架进行剖析,很不错值得学习借鉴,还有libevent中C语言的功底值得学习揣摩!

    libevent-0.7c 源码(资料中转)

     跟网络无关的,libevent也有一些缓冲区管理的函数,而且是c风格的函数,实用性不是太大。libevent没有提供缓存的函数。  虽然libevent实用上的价值不大,但它提供的接口形式还是不错的,实现类似的lib的时候仍然...

    libevent源码深度剖析

    《libevent源码深度剖析》一书主要针对的是libevent这一开源库进行深入解析,旨在帮助读者理解并掌握libevent的核心原理与应用。libevent是一个事件通知库,它允许程序员以一种统一的方式来处理各种类型的I/O事件和...

    libevent-master源码

    **二、libevent的主要功能** 1. **网络I/O**:libevent提供了对TCP、UDP、UNIX域套接字等协议的支持,可以方便地进行网络通信。 2. **定时器**:通过`event_base_new()`创建事件基后,可以使用`event_new()`创建...

    libevent参考手册(中文版)+libevent源码深度剖析

    《libevent参考手册(中文版)》和《libevent源码深度剖析》是两本针对libevent库的重要参考资料。libevent是一个开源的事件通知库,它使得开发者能够编写高性能、可扩展的网络服务器或者客户端应用。这个库的核心...

    libevent创建客户端&服务端demo

    你可以从libevent的官方网站获取源码,并按照官方的编译指南在VS2008环境中编译。编译完成后,你会得到.lib和.dll文件,这些都是你在项目中链接libevent库所必需的。 在创建客户端和服务端 demo 时,我们通常会涉及...

    libevent-1.0d 源码(资料中转)

    libevent-1.0d.tar.gz [GPG Sig] - Release 2005-04-22 Several minor bug fixes and building of shared libraries. libevent-1.0c.tar.gz [GPG Sig] - Release 2005-04...libevent-0.1.tar.gz - Release 2000-11-14

    libevent-1.0e源码(资料中转)

    libevent-1.0e.tar.gz [GPG Sig] - Release 2005-04-26 Important fix to bug in poll implementation introduced in 1.0d. libevent-1.0d.tar.gz [GPG Sig] - Release ...libevent-0.1.tar.gz - Release 2000-11-14

    epoll反应堆 libevent.c核心源码

    epoll反应堆 libevent.c核心源码

Global site tag (gtag.js) - Google Analytics