EasyDarwin 中使用epoll网络模型替换原来的select模型
来源:互联网 发布:无法加入网络 编辑:程序博客网 时间:2024/06/14 08:34
EasyDarwin是由国内开源流媒体团队维护的一款开源流媒体平台框架,在DSS基础上进行的开发。从2012年12月创建并发展至今,从原有的单服务的流媒体服务器形式,扩展成现在的云平台架构的开源项目,更好地帮助广大流媒体开发者和创业型企业快速构建流媒体服务平台。
DSS中使用select监听网络IO事件,由于select最大只支持1024个文件描述符,原因#define __FD_SETSIZE 1024,随着使用的fd增加,处理性能上也会下降;easy darwin对此进行了改进。
下面是easydarwin中epoll的封装
#include "epollEvent.h"#include <sys/errno.h>#include <sys/time.h>#include <map>#include "OSMutex.h"using namespace std;#if defined(__linux__)#define MAX_EPOLL_FD20000static int epollfd = 0; //epoll 描述符static epoll_event* _events = NULL; //epoll事件接收数组static int m_curEventReadPos = 0; //当前读事件位置,在epoll事件数组中的位置static int m_curTotalEvents = 0; //总的事件个数,每次epoll_wait之后更新static OSMutex sMaxFDPosMutex;//锁static bool canEpoll = false;//是否可以执行epoll_wait,避免频繁执行,浪费CPUstatic map<int ,void *> epollFdmap;//映射 fd和对应的RTSPSession对象/*函数名:epollInit功能:初始化epoll,创建epollfd,申请epoll事件接收内存*/int epollInit(){ epollfd = epoll_create(MAX_EPOLL_FD); if(_events == NULL) { _events = new epoll_event[MAX_EPOLL_FD];//we only listen the read event } if(_events == NULL) { perror("new epoll_event error:"); exit(1); } m_curEventReadPos = 0; m_curTotalEvents = 0;return 0;}/*函数名:addEpollEvent功能:增加一个epoll监听事件,参数1 请求结构 参数2 事件类型*/int addEpollEvent(struct eventreq *req,int event){ if(req == NULL) { return -1; }struct epoll_event ev;memset(&ev,0x0,sizeof(ev)); int ret = -1; OSMutexLocker locker(&sMaxFDPosMutex);//加锁,防止线程池中的多个线程执行该函数,导致插入监听事件失败 if(event == EV_RE) { ev.data.fd = req->er_handle; ev.events = EPOLLIN|EPOLLHUP|EPOLLERR;//level triggle ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,req->er_handle,&ev); } else if(event == EV_WR) { ev.data.fd = req->er_handle; ev.events = EPOLLOUT;//level triggle ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,req->er_handle,&ev); } else if(event == EV_RM) { ret = epoll_ctl(epollfd,EPOLL_CTL_DEL,req->er_handle,NULL);//remove all this fd events } else//epoll can not listen RESET {//we dont needed } epollFdmap[req->er_handle] = req->er_data; canEpoll = true;//每次新增事件后可以马上执行epoll_wait,新增了监听事件,意味着接下来可能马上要发生事件在这个fd上 return 0;}/*函数名:deleteEpollEvent功能:删除一个epoll监听事件,参数1 要删除的fd*/int deleteEpollEvent(int& fd){ int ret = -1; OSMutexLocker locker(&sMaxFDPosMutex); ret = epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,NULL);//remove all this fd events canEpoll = true;//每删除一个fd后,可以马上执行epoll_wait,可能在删除掉的fd上出现读异常 return 0;}/*函数名:epollwaitevent功能:等待epoll监听事件,返回事件个数*/int epollwaitevent(){ if(canEpoll == false) { return -1; } int nfds = 0; int curreadPos = -1;//m_curEventReadPos;//start from 0 if(m_curTotalEvents <= 0)//当前一个epoll事件都没有的时候,执行epoll_wait { m_curTotalEvents = 0; m_curEventReadPos = 0; nfds = epoll_wait(epollfd,_events,MAX_EPOLL_FD,15000); if(nfds > 0) { canEpoll = false;//wait到了epoll事件,先处理完再wait m_curTotalEvents = nfds; } else if(nfds < 0) { } else if(nfds == 0) { canEpoll = true;//这一次wait超时了,下一次继续wait } } if(m_curTotalEvents)//从事件数组中每次取一个,取的位置通过m_curEventReadPos设置 { curreadPos = m_curEventReadPos; m_curEventReadPos ++; if(m_curEventReadPos >= m_curTotalEvents - 1) { m_curEventReadPos = 0; m_curTotalEvents = 0; } } return curreadPos;}/*函数名:epoll_waitevent功能:等待一个epoll监听事件,返回一个事件,参数1:返回事件的指针 参数2 忽略*/int epoll_waitevent(struct eventreq *req, void* onlyForMOSX){ int eventPos = -1; eventPos = epollwaitevent(); if(eventPos >= 0) { req->er_handle = _events[eventPos].data.fd; if(_events[eventPos].events == EPOLLIN|| _events[eventPos].events == EPOLLHUP|| _events[eventPos].events == EPOLLERR) { req->er_eventbits = EV_RE;//we only support read event } else if(_events[eventPos].events == EPOLLOUT) { req->er_eventbits = EV_WR; } req->er_data = epollFdmap[req->er_handle]; OSMutexLocker locker(&sMaxFDPosMutex); deleteEpollEvent(req->er_handle); return 0; } return EINTR;}/*函数名:epollDestory功能:销毁epoll,析构的时候*/int epollDestory(){ delete[] _events; return 0;}#endif1.启动服务器调用StartServer时会执行::epollInit()
2.调用EventContext::RequestEvent注册IO网络事件时会执行addEpollEvent(&fEventReq, theMask)
3.事件监听线程执行EventThread::Entry()时,调用epoll_waitevent(&theCurrentEvent, NULL)阻塞等待注册的IO事件发生
4.EventContext::Cleanup()执行时会调用deleteEpollEvent(int& fd)清除注册的IO网络事件
阅读全文
0 0
- EasyDarwin 中使用epoll网络模型替换原来的select模型
- select和epoll网络模型
- Linux select/epoll网络模型
- libevent for qt网络模块,直接替换qt的select模型,支持epoll,select,pool.使用非常简单,无需修改以前的代码结构
- 面向接口的网络处理模型(封装select, epoll, poll)
- select、poll、epoll 网络模型比较
- linux网络编程 select,poll,epoll模型
- 网络I/O模型select/poll/epoll
- linux的网络模型---epoll
- select、epoll模型概念
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
- 开源流媒体服务器EasyDarwin支持epoll网络模型,大大提升流媒体服务器网络并发性能
- socket通信网络模型 ——Epoll、IOCP模型详解以及与select、kqueue等常见模型的区别特点
- linux效率优于select的epoll模型
- select poll epoll的io模型
- select poll 与epoll模型的总结
- select模型的使用
- select模型的使用
- 孤儿进程与僵死进程
- C++ new的理解
- Dubbo+Zookeeper+SpringMVC:基于注解的配置方法
- RetroFactory
- 学Java就来吧
- EasyDarwin 中使用epoll网络模型替换原来的select模型
- hihoCoder
- 第八个实验 PWM控制蜂鸣器
- [BZOJ1854][Scoi2010]游戏
- 渠道分销系统开发管理
- php+mysql+jquery创建简单网页聊天室
- Java核心技术-异常处理
- java高级(一)
- 人工智能从入门到精通(3)