- 浏览: 1386369 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
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 5082我的gcc版本是4.4.1 先来看const和define以 ... -
gdb学习笔记(一)
2009-10-17 14:11 11662这里只是一个摘要。具体的细节还需要去看manual。 1 ... -
ydb的内存模型
2009-09-06 18:02 1902阿宝同学推荐了这个东 ... -
glibc中strlen的实现
2009-08-04 09:10 4479glibc中的strlen的实现主要的思想就是每次检测4个字节 ... -
libevent源码浅析(四)
2009-05-15 23:02 4379最近刚刚一个项目自己用libevent,因此这几天又把libe ... -
libevent源码浅析(二)
2009-02-22 00:11 4041我们来看下libevent的定时器的实现 在libevent ... -
libevent源码浅析(一)
2009-02-14 13:23 7347这里分析的是libevent-1.4.9。 PS:前面还看了 ... -
linux下的time处理
2009-01-04 18:02 6789在内核中有3个不同的时间: Wall time(real t ... -
libev简单使用介绍
2008-12-30 09:52 11413更详细的用法请看他的 ... -
linux下的elf结构
2008-12-12 00:20 5134可以看到链接器和加载器看待elf是完全不同的,链接器看到 ... -
php的c扩展
2008-12-07 18:24 4528在php中最核心的一个数据结构就是这个: typedef u ... -
linux下的管理内存相关的函数
2008-11-27 00:56 4420malloc的实现,在linux下的实现是这样的,当所需 ... -
linux下的数据对齐
2008-11-25 12:15 3600数据对齐也就是通过硬件来估算在数据的地址和内存块之间的联系。当 ... -
linux下检测ip冲突
2008-11-16 20:18 8071原理其实很简单,那就是广播一个arp包,然后recv,如果没有 ... -
今天碰到的一个问题
2008-10-29 22:33 1221将位图用 bmptopnm 转成pcl6的打印语言,然后直接c ... -
ftruncate和msync
2008-10-23 22:10 3436int ftruncate(int fd, off_t le ... -
GUN C正则表达式
2008-09-25 23:47 6143最近项目中要处理文本,因此就用了gun的正则表达式,它是pos ... -
看代码看的头晕
2008-09-06 01:04 1814最近工作需要在看ghostscript的代码,看得我头晕眼花, ... -
[转帖]MISRA--作为工业标准的C编程规范
2008-08-21 13:19 2798本文档转贴自孟岩的blog ... -
代码大全读书笔记1
2008-04-26 19:16 3786这么好的书,觉得写点东西,记录一下比较好。 4.1选择编程语 ...
相关推荐
为方便阅读,把blog上的libevent源码深度剖析系列文章整合成一个pdf。
libevent源码深度剖析 libevent源码深度剖析 libevent源码深度剖析 libevent源码深度剖析 libevent源码深度剖析
libevent是非常著名的开源网络库,可以作为服务端开发入门研究资料
Libevent源码解析.pdf
libevent库,文字版,很清晰,附带libevent参考手册(中文版) libevent源码深度剖析,根据libevent开源代码框架进行剖析,很不错值得学习借鉴,还有libevent中C语言的功底值得学习揣摩!
作者连接为http://blog.csdn.net/luotuo44/article/category/2435521/2 本人为方便今后的学习和记录,将网页内容复制做成PDF文档,希望作者不要介意
libevent源码解析
libevent参考手册(中文版) + libevent源码深度剖析 zszszs
最新jm源码、最新libevent源码,放心下载,安心使用,
Libevent源码和资料合集 Libevent源码和资料合集
libevent源码深度解析
该资源为libevent库源码,2.1.8stable,用于编译libevent相关库文件,编译过程及使用库创建http https server可参照本账号博客文章。
libevent 源码深度剖析.pdf libevent 源码 深度 剖析 pdf
libevent源码及库文件
libevent源码深度剖析:主要介绍libevent框架,以及重要流程.
libevent资源合集,包括libevnet深入浅出,文字版PDF。libevent参考手册,文字版PDF。libevent源码深度剖析,文字版PDF。基于libevent打车移动解决方案,libevent实战项目。学习libevent可以下载参考学习。
libevent源码剖析额,不多说,不适合想用来快速进行网络编程的人。因为这本书不讲解怎么使用网络api,而是讲解的网络编程所遇到的问题,然后通过一个优秀的开源网络库来讲解,它是怎么克服这些困难的。适合想深入...