php-fpm epoll封装
参考 http://www.jianshu.com/p/dac223d7d9ad
事件对象结构
//fpm_event.h
struct fpm_event_s {
int fd; /* IO 文件句柄*/
struct timeval timeout;
struct timeval frequency;
void (*callback)(struct fpm_event_s *, short, void *); /* 回调函数 */
void *arg; /* 回调函数的参数 */
int flags;
int index;
short which;
};
//队列,多个事件对象的容器
typedef struct fpm_event_queue_s {
struct fpm_event_queue_s *prev;
struct fpm_event_queue_s *next;
struct fpm_event_s *ev;
} fpm_event_queue;
事件模块封装结构
struct fpm_event_module_s {
const char *name;
int support_edge_trigger;
int (*init)(int max_fd);
int (*clean)(void);
//等待多个事件
int (*wait)(struct fpm_event_queue_s *queue, unsigned long int timeout);
int (*add)(struct fpm_event_s *ev);
int (*remove)(struct fpm_event_s *ev);
};
//events/epoll.c
//环境变量,在编译时确定是否纳入.
#if HAVE_EPOLL #include <sys/epoll.h>
#include <errno.h> static int fpm_event_epoll_init(int max);
static int fpm_event_epoll_clean();
static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
static int fpm_event_epoll_add(struct fpm_event_s *ev);
static int fpm_event_epoll_remove(struct fpm_event_s *ev); static struct fpm_event_module_s epoll_module = {
.name = "epoll",
.support_edge_trigger = ,
.init = fpm_event_epoll_init,
.clean = fpm_event_epoll_clean,
.wait = fpm_event_epoll_wait,
.add = fpm_event_epoll_add,
.remove = fpm_event_epoll_remove,
}; //全局变量
static struct epoll_event *epollfds = NULL;
static int nepollfds = ;
static int epollfd = -; #endif /* HAVE_EPOLL */ //这是使用时,获取模块对象的函数
//系统不支持返回NULL,这个函数总是编入二进制文件里.
struct fpm_event_module_s *fpm_event_epoll_module() /* {{{ */
{
#if HAVE_EPOLL
return &epoll_module;
#else
return NULL;
#endif /* HAVE_EPOLL */
}
/* }}} */ #if HAVE_EPOLL /*
* Init the module
*/
static int fpm_event_epoll_init(int max) /* {{{ */
{
if (max < ) {
return ;
} /* init epoll */
epollfd = epoll_create(max + );
if (epollfd < ) {
zlog(ZLOG_ERROR, "epoll: unable to initialize");
return -;
} /* allocate fds */
epollfds = malloc(sizeof(struct epoll_event) * max);
if (!epollfds) {
zlog(ZLOG_ERROR, "epoll: unable to allocate %d events", max);
return -;
}
memset(epollfds, , sizeof(struct epoll_event) * max); /* save max */
nepollfds = max; return ;
}
/* }}} */ /*
* Clean the module
*/
static int fpm_event_epoll_clean() /* {{{ */
{
/* free epollfds */
if (epollfds) {
free(epollfds);
epollfds = NULL;
}
if (epollfd != -) {
close(epollfd);
epollfd = -;
} nepollfds = ; return ;
}
/* }}} */ /*
* wait for events or timeout
*/
static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
{
int ret, i; /* ensure we have a clean epoolfds before calling epoll_wait() */
memset(epollfds, , sizeof(struct epoll_event) * nepollfds); /* wait for inconming event or timeout */
ret = epoll_wait(epollfd, epollfds, nepollfds, timeout);
if (ret == -) { /* trigger error unless signal interrupt */
if (errno != EINTR) {
zlog(ZLOG_WARNING, "epoll_wait() returns %d", errno);
return -;
}
} /* events have been triggered, let's fire them */
for (i = ; i < ret; i++) { /* do we have a valid ev ptr ? */
if (!epollfds[i].data.ptr) {
continue;
} /* fire the event */
fpm_event_fire((struct fpm_event_s *)epollfds[i].data.ptr); /* sanity check */
if (fpm_globals.parent_pid != getpid()) {
return -;
}
} return ret;
}
/* }}} */ /*
* Add a FD to the fd set
*/
static int fpm_event_epoll_add(struct fpm_event_s *ev) /* {{{ */
{
struct epoll_event e; /* fill epoll struct */
e.events = EPOLLIN;
e.data.fd = ev->fd; //data.ptr 设为自定义对象, 事件触发时,以此获取自定义对象
e.data.ptr = (void *)ev; if (ev->flags & FPM_EV_EDGE) {
e.events = e.events | EPOLLET;
} /* add the event to epoll internal queue */
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ev->fd, &e) == -) {
zlog(ZLOG_ERROR, "epoll: unable to add fd %d", ev->fd);
return -;
} /* mark the event as registered */
ev->index = ev->fd;
return ;
}
/* }}} */ /*
* Remove a FD from the fd set
*/
static int fpm_event_epoll_remove(struct fpm_event_s *ev) /* {{{ */
{
struct epoll_event e; /* fill epoll struct the same way we did in fpm_event_epoll_add() */
e.events = EPOLLIN;
e.data.fd = ev->fd;
e.data.ptr = (void *)ev; if (ev->flags & FPM_EV_EDGE) {
e.events = e.events | EPOLLET;
} /* remove the event from epoll internal queue */
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, &e) == -) {
zlog(ZLOG_ERROR, "epoll: unable to remove fd %d", ev->fd);
return -;
} /* mark the event as not registered */
ev->index = -;
return ;
}
/* }}} */ #endif /* HAVE_EPOLL */
fpm_event_set(&signal_fd_event, fpm_signals_get_fd(), FPM_EV_READ, &fpm_got_signal, NULL);
初始化变量 ev
int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg) /* {{{ */
{
if (!ev || !callback || fd < -) {
return -;
}
memset(ev, , sizeof(struct fpm_event_s));
ev->fd = fd;
ev->callback = callback;
ev->arg = arg;
ev->flags = flags;
return ;
}
fpm_event_add(&signal_fd_event, );
如果是io事件 则放到epoll_ctl,如果是定时器,则放到定时器队列里
int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
{
struct timeval now;
struct timeval tmp;
if (!ev) {
return -;
}
ev->index = -;
/* it's a triggered event on incoming data */
if (ev->flags & FPM_EV_READ) {
ev->which = FPM_EV_READ;
if (fpm_event_queue_add(&fpm_event_queue_fd, ev) != ) {
return -;
}
return ;
}
/* it's a timer event */
ev->which = FPM_EV_TIMEOUT;
fpm_clock_get(&now);
if (frequency >= ) {
tmp.tv_sec = frequency / ;
tmp.tv_usec = (frequency % ) * ;
} else {
tmp.tv_sec = ;
tmp.tv_usec = frequency * ;
}
ev->frequency = tmp;
fpm_event_set_timeout(ev, now);
if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != ) {
return -;
}
return ;
}
如果是io事件,则放到epoll_ctl里
static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
{
struct fpm_event_queue_s *elt;
if (!queue || !ev) {
return -;
}
if (fpm_event_queue_isset(*queue, ev)) {
return ;
}
if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
zlog(ZLOG_SYSERROR, "Unable to add the event to queue: malloc() failed");
return -;
}
elt->prev = NULL;
elt->next = NULL;
elt->ev = ev;
if (*queue) {
(*queue)->prev = elt;
elt->next = *queue;
}
*queue = elt;
/* ask the event module to add the fd from its own queue */
if (*queue == fpm_event_queue_fd && module->add) {
module->add(ev);
}
return ;
}
执行事件
void fpm_event_fire(struct fpm_event_s *ev) /* {{{ */
{
if (!ev || !ev->callback) {
return;
}
(*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg);
}
php-fpm epoll封装的更多相关文章
- 基于epoll封装的事件回调miniserver
epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...
- RBL开发笔记二
17:13:55 2014-08-25 有以下几个点: 第一 :怎么在预处理阶段能够做到识别某个宏是否给定义了 这里就定义了一个SystemConfig.h 专门做这个事情 当然是需要make ...
- Python 中的进程、线程、协程、同步、异步、回调
进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说 ...
- 协程,greenlet,gevent
""" 协程 """ ''' 协程: 类似于一个可以暂停的函数,可以多次传入数据,可以多次返回数据 协程是可交互的 耗资源大小:进程 --& ...
- libevent学习笔记(参考libevent深度剖析)
最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的<Libevent源码深度剖析>, 参考资料: http://blog.csdn.net/spark ...
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...
- Java nio 空轮询bug到底是什么
编者注:Java nio 空轮询bug也就是Java nio在Linux系统下的epoll空轮询问题. epoll机制是Linux下一种高效的IO复用方式,相较于select和poll机制来说.其高效 ...
- 使用Cadence绘制PCB流程
转载:https://blog.csdn.net/hailin0716/article/details/47169799 之前使用过cadence画过几块板子,一直没有做过整理.每次画图遇到问题时,都 ...
- 框架篇:见识一下linux高性能网络IO+Reactor模型
前言 网络I/O,可以理解为网络上的数据流.通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写.单个socket时,使用一个线程即可高效处理:然而如果是10K个socket连接 ...
随机推荐
- Java常用的输出调试技巧
--------siwuxie095 Eclipse 开发中常用的输出调试技巧: 先在左侧的 Package Explorer,右键->New->J ...
- [Selenium]计算坐标进行拖拽,重写dragAndDropOffset
//@author jzhang6 public void dragAndDropOffset(WebDriver driver,WebElement dragableEl, WebElement d ...
- MyEclipse文件查找技巧
只为成功找方法,不为失败找借口! MyEclipse使用总结——MyEclipse文件查找技巧 一.查找文件 使用快捷键[ctrl+shift+R]弹出弹出文件查找框,如下图所示: 二.查找包含某个字 ...
- 一起做RGB-D SLAM(8) (关于调试与补充内容)
“一起做”系列完结后,我收到不少同学给我的反馈.他们提了一些在程序编译/运行过程中的问题.我把它们汇总起来,组成了这个“补充篇”.你也可以看成是一个Q&A. Q: OpenCV的版本?A: 我 ...
- Android Gson 操作
JSON序列化后的数据不带类名与名命空间,所以这两个服务端跟客户端可以不对应,需要保证字段对应即可 Asp.net MVC端 using System; using System.Collection ...
- oracle RAC 创库,停启库,删除库
1.创建数据库的命令dbca -silent -createDatabase -templateName General_Purpose.dbc -gdbname FPCSDB2 -sid FPCSD ...
- msfvenom木马生成+免杀+壳(实测并不能免杀)
msfvenom 选项: -p, --payload 有效载荷使用.指定一个有效的自定义载荷 --payload-options 列出有效载荷的标准选项 -l, --list [type] 列出一个模 ...
- Summary #ToBeContinue......
一.请回望暑假时的第一次作业,你对于软件工程课程的想象1)对比开篇博客你对课程目标和期待,“希望通过实践锻炼,增强计算机专业的能力和就业竞争力”,对比目前的所学所练所得,在哪些方面达到了你的期待和目标 ...
- 试题 H: 人物相关性分析 第十届蓝桥杯
试题 H: 人物相关性分析时间限制: 1.0s 内存限制: 512.0MB 本题总分: 20 分[问题描述]小明正在分析一本小说中的人物相关性.他想知道在小说中 Alice 和 Bob有多少次同时出现 ...
- leancloud 云引擎
可以部署网站的云端,云代码的升级版.