参考 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封装的更多相关文章

  1. 基于epoll封装的事件回调miniserver

    epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...

  2. RBL开发笔记二

     17:13:55 2014-08-25 有以下几个点:  第一 :怎么在预处理阶段能够做到识别某个宏是否给定义了  这里就定义了一个SystemConfig.h 专门做这个事情  当然是需要make ...

  3. Python 中的进程、线程、协程、同步、异步、回调

    进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说 ...

  4. 协程,greenlet,gevent

    """ 协程 """ ''' 协程: 类似于一个可以暂停的函数,可以多次传入数据,可以多次返回数据 协程是可交互的 耗资源大小:进程 --& ...

  5. libevent学习笔记(参考libevent深度剖析)

    最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的<Libevent源码深度剖析>, 参考资料: http://blog.csdn.net/spark ...

  6. Go netpoll I/O 多路复用构建原生网络模型之源码深度解析

    导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...

  7. Java nio 空轮询bug到底是什么

    编者注:Java nio 空轮询bug也就是Java nio在Linux系统下的epoll空轮询问题. epoll机制是Linux下一种高效的IO复用方式,相较于select和poll机制来说.其高效 ...

  8. 使用Cadence绘制PCB流程

    转载:https://blog.csdn.net/hailin0716/article/details/47169799 之前使用过cadence画过几块板子,一直没有做过整理.每次画图遇到问题时,都 ...

  9. 框架篇:见识一下linux高性能网络IO+Reactor模型

    前言 网络I/O,可以理解为网络上的数据流.通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写.单个socket时,使用一个线程即可高效处理:然而如果是10K个socket连接 ...

随机推荐

  1. Jquery的树插件jqxTreeGrid的使用小结(实现基本的增删查改操作)

    一.引入相应的js <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" t ...

  2. 为Eclipse安装功能扩展插件

    ---------siwuxie095                 关于 Eclipse 的下载.安装与配置,详见本人博客分类:利剑出鞘, 里面的 Eclipse的配置         本人博客( ...

  3. loadrunner12-参数化以及参数化关联

    1.选中需要进行参数化的字段,单击鼠标右键,选择使用参数替换--新建参数. 2.输入参数名称. 3.根据需要进行选择,我这边选择“Yes”. 4.再次选中刚刚参数化的字段,单击鼠标右键,选择 显示参数 ...

  4. 交互原型画得丑?29个优秀UI/UX线框草图

    现在越来越多UI设计师都需要画一些交互的线框图,然而作为视觉专家,当然要把它画得靓靓的嘛,是不是?所以很多用户会使用<5款高效的原型设计工具>来绘制,或者直接手绘更有逼格. 今天达人手工整 ...

  5. cmake 及make 实践记录

    DEBIAN操作系统 预备操作: 安装 gcc g++ make cmake 开启Terminal 切换到超级用户 下载安装上述软件 A@debian:~$ su Password: root@deb ...

  6. Java程序设计17——多线程-Part-A

    1 多线程 1.1 简介 大部分时候,我们编写的程序都是单线程的.也就是都只有一条顺序执行流:程序从main方法开始执行,依次向下执行每行代码,如果程序执行某行代码遇到了阻塞,则程序会停滞在该处.如果 ...

  7. java通过经纬度计算两个点的之间的距离的算法

    通过两个点的经纬度计算距离 从google maps的脚本里扒了段代码,没准啥时会用上.大家一块看看是怎么算的. private const double EARTH_RADIUS = 6378.13 ...

  8. Android 上传文件到XP

    Android部分: AsyncHttpClient client = new AsyncHttpClient(); RequestParams requestParams = new Request ...

  9. CentOS 7下面配置静态IP

    CentOS 7.0系统是一个很新的版本哦,很多朋友都不知道CentOS 7.0系统是怎么去安装配置的哦,因为centos7.0与以前版本是有很大的改进哦. 说明:截止目前CentOS 7.x最新版本 ...

  10. Linux的系统引导

    启动引导: 1.主机加电自检,加载BIOS信息 2.读取MBR的引导文件[grub lilo] 3.引导linux内核 4.运行第一个进程init pid=1 5.进入相应的运行级别[0-6] 6.运 ...