epoll学习
来源:互联网 发布:游龙网络靠什么赚钱的 编辑:程序博客网 时间:2024/06/05 19:14
参考文章:
http://blog.163.com/huchengsz@126/blog/static/73483745201181824629285/
百度百科
epoll是在内核2.5.44中引进的。
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。
epoll系统调用:epoll_create, epoll_ctl和poll_wait
include/linux/posix_types.h:
#define __FD_SETSIZE 1024
select只能支持1024文件描述符的检测。
epoll的工作模式
令人高兴的是,2.6内核的epoll比其2.5开发版本的/dev/epoll简洁了许多,所以,大部分情况下,强大的东西往往是简单的。唯一有点麻烦 是epoll有2种工作方式:LT和ET。
LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你 的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.
ET (edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述 符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致 了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(on
Epoll模型主要负责对大量并发用户的请求进行及时处理,完成服务器与客户端的数据交互。其具体的实现步骤如下:
(a) 使用epoll_create()函数创建文件描述,设定将可管理的最大socket描述符数目。
(b) 创建与epoll关联的接收线程,应用程序可以创建多个接收线程来处理epoll上的读通知事件,线程的数量依赖于程序的具体需要。
(c) 创建一个侦听socket描述符ListenSock;将该描述符设定为非阻塞模式,调用Listen()函数在套接字上侦听有无新的连接请求,在 epoll_event结构中设置要处理的事件类型EPOLLIN,工作方式为 epoll_ET,以提高工作效率,同时使用epoll_ctl()注册事件,最后启动网络监视线程。
(d) 网络监视线程启动循环,epoll_wait()等待epoll事件发生。
(e) 如果epoll事件表明有新的连接请求,则调用accept()函数,将用户socket描述符添加到epoll_da
(f) 如果epoll事件表明socket描述符上有数据可读,则将该socket描述符加入可读队列,通知接收线程读入数据,并将接收到的数据放入到接收数据 的链表中,经逻辑处理后,将反馈的数据包放入到发送数据链表中,等待由发送线程发送。
01 //epoll_wait范围之后应该是一个循环,遍利所有的事件:02 for (n = 0; n < nfds; ++n)03 {04 if (events[n].data.fd == listener)05 {//如果是主socket的事件的话,则表示有新连接进入了,进行新连接的处理。06 client = accept (listener, (struct sockaddr *) &local, &addrlen);07 if (client < 0)08 {09 perror ("accept");10 continue;11 }12 setnonblocking (client); // 将新连接置于非阻塞模式13 ev.events = EPOLLIN | EPOLLET; // 并且将新连接也加入EPOLL的监听队列。14 //注意,这里的参数EPOLLIN | EPOLLET并没有设置对写socket的监听,15 //如果有写操作的话,这个时候epoll是不会返回事件的,16 //如果要对写操作也监听的话,应该是EPOLLIN | EPOLLOUT | EPOLLET17 ev.data.fd = client;18 if (epoll_ctl (kdpfd, EPOLL_CTL_ADD, client, &ev) < 0)19 {20 /*21 设置好event之后,将这个新的event通过epoll_ctl加入到epoll的监听队列里面,22 这里用EPOLL_CTL_ADD来加一个新的epoll事件,通过EPOLL_CTL_DEL来减少一个epoll事件,通23 过EPOLL_CTL_MOD来改变一个事件的监听方式.24 */25 fprintf (stderr, "epoll set insertion error: fd=%d", client);26 return -1;27 }28 }29 else // 如果不是主socket的事件的话,则代表是一个用户socket的事件,30 do_use_fd (events[n].data.fd); //则来处理这个用户socket的事情,比如说read(fd,xxx)之类的,或者一些其他的处理。31 }对,epoll的操作就这么简单,总共不过4个 API:epoll_create, epoll_ctl, epoll_wait和close。
如果您对epoll的效率还不太了解,请参考我 之前关于网络游戏的网络编程等相关的文章。
以前公司的服务器都是使用HTTP连接,但是这样的话,在手机目前的网络情况下不但显得速度较慢,而且不稳定。因此大家一致同意用 SOCKET来进行连接。虽然使用SOCKET之后,对于用户的费用可能会增加(由于是用了CMNET而非CMWAP),但是,秉着用户体验至上的原则, 相信大家还是能够接受的(希望那些玩家月末收到帐单不后能够保持克制...)。
这次的服务器设计中,最重要的一个突破,是使用了EPOLL模型, 虽然对之也是一知半解,但是既然在各大PC网游中已经经过了如此严酷的考验,相信他不会让我们失望,使用后的结果,确实也是表现相当不错。在这里,我还是 主要大致介绍一下这个模型的结构。
6、Linux下EPOll编程实例
EPOLL模型似乎只有一种格式,所以大家只要参考我下面的代码, 就能够对EPOLL有所了解了,代码的解释都已经在注释中:
while (TRUE)02 {03 int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT); //等待EPOLL时间的发生,相当于监听,04 //至于相关的端口,需要在初始化EPOLL的时候绑定。05 if (nfds <= 0)06 continue;07 m_bOnTimeChecking = FALSE;08 G_CurTime = time (NULL);09 for (int i = 0; i < nfds; i++)10 {11 try12 {13 if (m_events[i].data.fd == m_listen_http_fd) //如果新监测到一个HTTP用户连接到绑定的HTTP端口,14 //建立新的连接。由于我们新采用了SOCKET连接,所以基本没用。15 {16 OnAcceptHttpEpoll ();17 }18 else if (m_events[i].data.fd == m_listen_sock_fd) //如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,19 //建立新的连接。20 {21 OnAcceptSockEpoll ();22 }23 else if (m_events[i].events & EPOLLIN) //如果是已经连接的用户,并且收到数据,那么进行读入。24 {25 OnReadEpoll (i);26 }27 28 OnWriteEpoll (i); //查看当前的活动连接是否有需要写出的数据。29 }30 catch (int)31 {32 PRINTF ("CATCH捕获错误\n");33 continue;34 }35 }36 m_bOnTimeChecking = TRUE;37 OnTimer (); //进行一些定时的操作,主要就是删除一些短线用户等。38 }
<3>使用mmap加速内核 与用户空间的消息传递。Linux 2.5的时候需要手动映射。
- epoll 学习
- epoll学习
- EPOLL学习
- epoll()学习
- 学习epoll
- epoll学习
- epoll学习
- epoll学习
- epoll学习
- EPOLL学习
- epoll详解-epoll学习笔记
- epoll学习,epoll与select,pool区别
- epoll学习笔记
- epoll学习笔记
- EPOLL 边缘触发学习
- EPOLL 边缘触发学习
- epoll学习笔记
- epoll学习笔记
- Java 获取指定字符串出现的次数
- --------------------------STDAPI释义-----------------------------------
- IOS中获取各个文件的目录路径的方法和NSFileManager类
- SQL语句实现取消自增列属性(修改自增列值)
- JDK 的安装及环境变量的配置
- epoll学习
- Eclipse添加builder自动执行bat复制脚本
- 递归与分治:邮局选址问题。
- 设计模式—代理模式
- 分享 WeCenter社交化问答系统 v2.5 源代码
- IOS开发之格式化日期时间
- 学会等待,享受孤独!
- 【Linux】一张图让你读懂Linux内核运行原理
- Java实现定时任务的三种方法