Reactor模式 和epoll

a, Handle表示句柄,文件描述符、socket等;b, EventDemultiplexer表示多路分发机制,调用系统提供的多IO路复用,比如select,epoll。程序先将关注的句柄注册到EventDemultiplexer,当有相关事件到来触发EventDemultiplexer通知程序。c, EventHandler定义事件处理方法,d, Reactor是事件管理的接口,注册和销毁事件,并运行事件循环,当EventDemultiplexer返回Handle有事件"就绪",将其分发给EventHandler上对应的方法。e, ConcreteEventhandler实现每个事件的处理逻辑。

epoll原理:    struct eventpoll{          /*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/          struct rb_root  rbr;          /*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/          struct list_head rdlist;          ...    };每一个epoll对象都有一个独立的eventpoll结构体,当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。

对于每一个事件,都会建立一个epitem结构体struct epitem{          struct rb_node  rbn;//红黑树节点          struct list_head    rdllink;//双向链表节点          struct epoll_filefd  ffd;  //事件句柄信息          struct eventpoll *ep;    //指向其所属的eventpoll对象          struct epoll_event event; //期待发生的事件类型      } 

epoll_wait在for循环中检查epitem中有没有已经完成的事件,有的话就把结果返回。没有的话调用schedule_timeout()进入休眠,直到进程被再度唤醒或者超时。

LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时次次返回这个句柄,而ET模式仅在第一次返回。当一个socket句柄上有事件时,内核会把该句柄插入上面所说的准备就绪list链表,这时我们调用epoll_wait,会把准备就绪的socket拷贝到用户态内存,然后清空准备就绪list链表,最后,epoll_wait干了件事,就是检查这些socket,如果不是ET模式(就是LT模式的句柄了),并且这些socket上确实有未处理的事件时,又把该句柄放回到刚刚清空的准备就绪链表了。

struct epoll_event ev,events[20]; //ev用于注册事件,数组用于回传要处理的事件ev.data.fd=listenfd; //设置与要处理的事件相关的文件描述符ev.events=EPOLLIN|EPOLLET; //设置要处理的事件类型

epfd=epoll_create(256);epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);

for( ; ; ) {        nfds = epoll_wait(epfd,events,20,500);        for(i=0;i<nfds;++i)        {            if(events[i].data.fd==listenfd) //有新的连接            {                connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); //accept这个连接                ev.data.fd=connfd;                ev.events=EPOLLIN|EPOLLET;                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //将新的fd添加到epoll的监听队列中            }            else if( events[i].events&EPOLLIN ) //接收到数据,读socket            {                sockfd=events[i].data.fd;                n = read(sockfd, line, MAXLINE)) < 0    //读                ev.data.ptr = md;     //md为自定义类型,添加数据                ev.events=EPOLLOUT|EPOLLET;                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改标识符,等待下一个循环时发送数据,异步处理的精髓            }            else if(events[i].events&EPOLLOUT) //有数据待发送,写socket            {                struct myepoll_data* md = (myepoll_data*)events[i].data.ptr;    //取数据                sockfd = md->fd;                send( sockfd, md->ptr, strlen((char*)md->ptr), 0 );        //发送数据                ev.data.fd=sockfd;                ev.events=EPOLLIN|EPOLLET;                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改标识符,等待下一个循环时接收数据            }            else            {                //其他的处理            }        }    }

时间: 2024-08-08 13:54:39

Reactor模式 和epoll的相关文章

IO复用(Reactor模式和Preactor模式)——用epoll来提高服务器并发能力

上篇线程/进程并发服务器中提到,提高服务器性能在IO层需要关注两个地方,一个是文件描述符处理,一个是线程调度. IO复用是什么?IO即Input/Output,在网络编程中,文件描述符就是一种IO操作. 为什么要IO复用? 1.网络编程中非常多函数是阻塞的,如connect,利用IO复用可以以非阻塞形式执行代码. 2.之前提到listen维护两个队列,完成握手的队列可能有多个就绪的描述符,IO复用可以批处理描述符. 3.有时候可能要同时处理TCP和UDP,同时监听多个端口,同时处理读写和连接等.

libevent之Reactor模式

通过前边的一篇博文轻量级网络库libevent初探,我们知道libevent实际上是封装了不同操作系统下的/dev/poll.kqueue.event ports.select.poll和epoll事件机制,从而给我们提供一个统一的接口. libevent采用了Reactor I/O 设计模式,而Reactor是基于同步I/O机制的,所以libevent实际是一个基于同步I/O机制的库. 对于I/O设计模式,与Reactor相对应的还有Proactor.下边我们先来看下这两者的不同之处. Rea

muduo网络库学习笔记(9):Reactor模式的关键结构

Reactor模式简介 Reactor的意思是"反应堆",是一种事件驱动机制.它和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为"回调函数". moduo库Reactor模式的实现 muduo中Reactor的关键结构包括:EventLoop.Poller和Chann

C++服务器设计(一):基于I/O复用的Reactor模式

I/O模型选择 在网络服务端编程中,一个常见的情景是服务器需要判断多个已连接套接字是否可读,如果某个套接字可读,则读取该套接字数据,并进行进一步处理. 在最常用的阻塞式I/O模型中,我们对每个连接套接字通过轮流read系统调用获取可读数据.如图3-1所示,read系统调用将会把该线程阻塞,直到数据报到达且被复制到应用进程的缓冲区中时才会返回. 图3-1 阻塞式I/O模型 在阻塞式I/O模型中,数据可读和读取数据这两个操作被合并在了一个系统调用中,对于单个套接字是否可读的判断,必须要等到实际数据接

Reactor模式

对象行为类的设计模式,对同步事件分拣和派发.别名Dispatcher(分发器) Reactor模式是处理并发I/O比较常见的一种模式,用于同步I/O,中心思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上:一旦有I/O事件到来或是准备就绪(区别在于多路复用器是边沿触发还是水平触发),多路复用器返回并将相应I/O事件分发到对应的处理器中. Reactor的事件处理机制 普通函数调用的机制:程序调用某函数->函数执行,程序等待->函数将结果和控制权返回给程

muduo源码分析--Reactor模式在muduo中的使用

一. Reactor模式简介 Reactor释义"反应堆",是一种事件驱动机制.和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为"回调函数". 二. moduo库Reactor模式的实现 muduo主要通过3个类来实现Reactor模式:EventLoop,Chann

reactor模式与java nio

?? Reactor是由Schmidt, Douglas C提出的一种模式,在高并发server实现中广泛採用. 改模式採用事件驱动方式,当事件出现时,后调用对应的事件处理代码(Event Handler). 这个模式是高并发server的基础.如nginx和lighttpd. 这两种对大并发,但每一个请求处理都非常快的场景非常适合. 通常的web訪问就是这个特点. 结构 包含了5个部分,当中handle和Synchronous Event Demultiplexer有OS实现. Handles

ACE - Reactor模式源码剖析及具体实现(大量源码慎入)

原文出自http://www.cnblogs.com/binchen-china,禁止转载. 在之前的文章中提到过Reactor模式和Preactor模式,现在利用ACE的Reactor来实现一个基于Reactor框架的服务器. 首先回顾下Reactor模式和Preactor模式. Reactor模式: Reactor模式实现非常简单,使用同步IO模型,即业务线程处理数据需要主动等待或询问,主要特点是利用epoll监听listen描述符是否有响应,及时将客户连接信息放于一个队列,epoll和队列

muduo库源码剖析(一) reactor模式

一. Reactor模式简介Reactor释义"反应堆",是一种事件驱动机制.和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为"回调函数". 二. moduo库Reactor模式的实现 muduo主要通过3个类来实现Reactor模式:EventLoop,Channe