- 浏览: 1400085 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
这次我们来看libevent的信号的处理。
在libevent中通过使用socketpair建立一对流管道,也就是全双工管道,来将信号事件与句柄事件统一起来。
先来看数据结构:
接下来可以看几个主要的函数:
evsignal_init函数主要用来初始化一些数据结构。
evsignal_add方法用来加新的信号事件.
evsignal_handler就是所有信号的处理函数。
evsignal_process主要是用来将相应的信号事件加入到激活列表中,以便于调用相应的回调函数。
在libevent中通过使用socketpair建立一对流管道,也就是全双工管道,来将信号事件与句柄事件统一起来。
先来看数据结构:
struct evsignal_info { struct event ev_signal; ///<所属的event int ev_signal_pair[2]; ///<创建的流管道 int ev_signal_added; ///<信号是否已被加入到event中的标记。 volatile sig_atomic_t evsignal_caught; ///<事件触发标记,1表示有信号被触发 struct event_list evsigevents[NSIG]; ///<多个事件有可能注册到同一个信号,因此这里每个信号的事件都是一个event_list. sig_atomic_t evsigcaught[NSIG]; ///<由于一个信号可能被注册多次,这里保存信号被捕捉的次数 #ifdef HAVE_SIGACTION struct sigaction **sh_old; #else ev_sighandler_t **sh_old; #endif int sh_old_max; };
接下来可以看几个主要的函数:
evsignal_init函数主要用来初始化一些数据结构。
void evsignal_init(struct event_base *base) { int i; ///创建一对流管道 if (evutil_socketpair( AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) event_err(1, "%s: socketpair", __func__); ///设置fd FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]); FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]); ///初始化sig数据结构 base->sig.sh_old = NULL; base->sig.sh_old_max = 0; base->sig.evsignal_caught = 0; memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); /* initialize the queues for all events */ ///在libevent里面,所有的事件队列都用tail queue实现,linux下它使用的是linux自带的taile queue,具体用法可以去看man手册。 for (i = 0; i < NSIG; ++i) TAILQ_INIT(&base->sig.evsigevents[i]); ///设置非阻塞 evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); ///初始化event结构 event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal); base->sig.ev_signal.ev_base = base; base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; }
evsignal_add方法用来加新的信号事件.
int evsignal_add(struct event *ev) { int evsignal; struct event_base *base = ev->ev_base; struct evsignal_info *sig = &ev->ev_base->sig; ///信号事件不能使用读写来检测。 if (ev->ev_events & (EV_READ|EV_WRITE)) event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); ///得到信号值 evsignal = EVENT_SIGNAL(ev); assert(evsignal >= 0 && evsignal < NSIG); ///如果此信号的事件队列为空则说明此信号第一次被注册。因此设置信号处理函数,这里所有的信号都注册到相同的处理函数evsignal_handler,接下来我们会来分析这个函数。 if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) { event_debug(("%s: %p: changing signal handler", __func__, ev)); if (_evsignal_set_handler( base, evsignal, evsignal_handler) == -1) return (-1); /* catch signals if they happen quickly */ evsignal_base = base; /// if (!sig->ev_signal_added) { if (event_add(&sig->ev_signal, NULL)) return (-1); sig->ev_signal_added = 1; } } /* multiple events may listen to the same signal */ TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next); return (0); }
evsignal_handler就是所有信号的处理函数。
static void evsignal_handler(int sig) { int save_errno = errno; if (evsignal_base == NULL) { event_warn( "%s: received signal %d, but have no base configured", __func__, sig); return; } ///进入此函数,说明信号已经来临,因此这里设置捕捉次数,以及此信号已经被捕捉的标记。 evsignal_base->sig.evsigcaught[sig]++; evsignal_base->sig.evsignal_caught = 1; #ifndef HAVE_SIGACTION signal(sig, evsignal_handler); #endif ///流管道开始发送数据,说明信号已经来临。此时另一端就会检测到事件从而调用我们初始化注册的回调函数。 /* Wake up our notification mechanism */ send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0); errno = save_errno; }
evsignal_process主要是用来将相应的信号事件加入到激活列表中,以便于调用相应的回调函数。
void evsignal_process(struct event_base *base) { struct evsignal_info *sig = &base->sig; struct event *ev, *next_ev; sig_atomic_t ncalls; int i; base->sig.evsignal_caught = 0; for (i = 1; i < NSIG; ++i) { ///得到此信号的所有事件数。 ncalls = sig->evsigcaught[i]; if (ncalls == 0) continue; ///循环遍历,得到已发生的信号事件。 for (ev = TAILQ_FIRST(&sig->evsigevents[i]); ev != NULL; ev = next_ev) { next_ev = TAILQ_NEXT(ev, ev_signal_next); if (!(ev->ev_events & EV_PERSIST)) event_del(ev); event_active(ev, EV_SIGNAL, ncalls); } sig->evsigcaught[i] = 0; } }
发表评论
-
gcc的几个自动优化
2009-11-10 00:44 5142我的gcc版本是4.4.1 先来看const和define以 ... -
gdb学习笔记(一)
2009-10-17 14:11 11730这里只是一个摘要。具体的细节还需要去看manual。 1 ... -
ydb的内存模型
2009-09-06 18:02 1978阿宝同学推荐了这个东 ... -
glibc中strlen的实现
2009-08-04 09:10 4525glibc中的strlen的实现主要的思想就是每次检测4个字节 ... -
libevent源码浅析(四)
2009-05-15 23:02 4426最近刚刚一个项目自己用libevent,因此这几天又把libe ... -
libevent源码浅析(二)
2009-02-22 00:11 4075我们来看下libevent的定时器的实现 在libevent ... -
libevent源码浅析(一)
2009-02-14 13:23 7432这里分析的是libevent-1.4.9。 PS:前面还看了 ... -
linux下的time处理
2009-01-04 18:02 6841在内核中有3个不同的时间: Wall time(real t ... -
libev简单使用介绍
2008-12-30 09:52 11547更详细的用法请看他的 ... -
linux下的elf结构
2008-12-12 00:20 5186可以看到链接器和加载器看待elf是完全不同的,链接器看到 ... -
php的c扩展
2008-12-07 18:24 4570在php中最核心的一个数据结构就是这个: typedef u ... -
linux下的管理内存相关的函数
2008-11-27 00:56 4484malloc的实现,在linux下的实现是这样的,当所需 ... -
linux下的数据对齐
2008-11-25 12:15 3647数据对齐也就是通过硬件来估算在数据的地址和内存块之间的联系。当 ... -
linux下检测ip冲突
2008-11-16 20:18 8173原理其实很简单,那就是广播一个arp包,然后recv,如果没有 ... -
今天碰到的一个问题
2008-10-29 22:33 1264将位图用 bmptopnm 转成pcl6的打印语言,然后直接c ... -
ftruncate和msync
2008-10-23 22:10 3498int ftruncate(int fd, off_t le ... -
GUN C正则表达式
2008-09-25 23:47 6192最近项目中要处理文本,因此就用了gun的正则表达式,它是pos ... -
看代码看的头晕
2008-09-06 01:04 1867最近工作需要在看ghostscript的代码,看得我头晕眼花, ... -
[转帖]MISRA--作为工业标准的C编程规范
2008-08-21 13:19 2834本文档转贴自孟岩的blog ... -
代码大全读书笔记1
2008-04-26 19:16 3823这么好的书,觉得写点东西,记录一下比较好。 4.1选择编程语 ...
相关推荐
为方便阅读,把blog上的libevent源码深度剖析系列文章整合成一个pdf。
本文将对libevent源码进行分析,深入理解其实现原理以及关键的数据结构和函数接口。我们首先从libevent源码的整体架构开始,然后详细介绍一些重要的组件和它们的实现方式。 1. 开篇 在分析libevent源码之前,有必要...
在深入Libevent源码分析之前,需要了解它的核心概念,主要包括事件循环、事件处理器、IO事件、定时器事件、信号事件等。事件循环是Libevent的中枢,它在后台运行,检测事件源的变化,并触发相应的事件处理器。事件...
libevent库,文字版,很清晰,附带libevent参考手册(中文版) libevent源码深度剖析,根据libevent开源代码框架进行剖析,很不错值得学习借鉴,还有libevent中C语言的功底值得学习揣摩!
Libevent 源码解析 Libevent 是一个高性能的事件驱动库,广泛应用于网络编程和高性能服务器开发中。下面是对 Libevent 源码的深入剖析,涵盖了其架构设计、事件处理机制、Reactor 模式、事件循环、IO multiplexing...
libevent源码深度剖析
《libevent参考手册(中文版)》和《libevent源码深度剖析》是两本针对libevent库的重要参考资料。libevent是一个开源的事件通知库,它使得开发者能够编写高性能、可扩展的网络服务器或者客户端应用。这个库的核心...
《libevent源码深度剖析》 libevent是一个高度优化的事件通知库,广泛应用于网络编程,尤其是服务器端的高性能设计。它提供了一种抽象层,允许程序员以一致的方式处理各种类型的事件,包括文件描述符(如套接字)的...
标题"libevent 参考手册中文版及源码解析"表明了本次学习的主题,重点是libevent库,包含了中文参考手册和源码的深度解析。libevent是一个开源的事件通知库,它使开发者能够方便地处理各种网络事件,如TCP、UDP、...
**libevent库源码详解** libevent是一个高度可移植、事件驱动的网络库,它能够帮助程序员处理大量的并发连接,并且有效地利用系统资源。在2.1.8stable版本中,libevent提供了丰富的功能和优化,使其成为开发高性能...
标题中的“jm源码”和“libevent源码”指的是两个知名的开源项目,分别是JM(可能是Java Microservices的简称)和Libevent。这两个组件在IT领域,尤其是网络编程和服务器开发中扮演着重要角色。 首先,让我们深入...
libevent 源码深度剖析.pdf libevent 源码 深度 剖析 pdf
这个“Libevent源码和资料合集”包含了Libevent的核心源代码以及相关的学习资源,对于深入理解和使用Libevent至关重要。 Libevent 的主要功能是通过事件驱动模型来管理非阻塞I/O。它支持多种事件模型,包括epoll...
《libevent源码分析1》 在深入探讨libevent的源码之前,我们先来了解一下这个库的基本情况。libevent是一个高度可扩展的事件通知库,它用于编写高性能、高并发的网络服务器。它的核心功能是提供了一种高效的方式来...
**三、libevent 的使用步骤** 1. **初始化**:首先,需要调用`event_init`来初始化`libevent`库。 2. **事件基结构创建**:创建`event_base`结构体实例,它代表了事件循环。 3. **事件创建**:使用`event_new`...