回首页 回首页 ◎ 设为首页  
◎ 收藏本站  
◎ 给我留言  
  
  首 页  C/C++教程  C++之父的FAQ  C/C++动向  C/C++源代码  C/C++误区  Unix/Linux  下载中心  乱七八糟  蚂蚁的Blog  
  当前位置:首 页 >> Unix/Linux >> Unix/Linux 编程 >> [转] epoll 为我们带来了什么?
最 近 更 新
C++ Wrapper for pipe推荐
[转][图文] 教你把Vim改..推荐
[转] Epoll用法举例说明推荐
[转] epoll 为我们带来..
Syn Flood 攻击(C 语言..推荐
Unix 下模拟 TC 的 getc..
[转] GCC 安装指南推荐
[转] C 编译器 GCC 简单..
最 新 推 荐
C++ Wrapper for pipe推荐
[转][图文] 教你把Vim改..推荐
[转] Epoll用法举例说明推荐
Syn Flood 攻击(C 语言..推荐
[转] GCC 安装指南推荐
热 门 排 行
[转] C 编译器 GCC 简单..
[转] GCC 安装指南推荐
[转][图文] 教你把Vim改..推荐
Syn Flood 攻击(C 语言..推荐
Unix 下模拟 TC 的 getc..
[转] Epoll用法举例说明推荐
C++ Wrapper for pipe推荐
[转] epoll 为我们带来..
站 内 搜 索

Web stdcpp.cn
关键词

搜索方式

搜索范围

精确匹配
广 告

[转] epoll 为我们带来了什么?


来源:tarkey的专栏 作者:tarkey 等级:精品
发布于2007-09-24 20:06 被读431次 【字体:

Q:网络服务器的瓶颈在哪?
A:IO效率。

  在大家苦苦的为在线人数的增长而导致的系统资源吃紧上的问题正在发愁的时候,Linux 2.6内核中提供的System Epoll为我们提供了一套完美的解决方案。传统的select以及poll的效率会因为在线人数的线形递增而导致呈二次乃至三次方的下降,这些直接导致了网络服务器可以支持的人数有了个比较明显的限制。

  自从Linux提供了/dev/epoll的设备以及后来2.6内核中对/dev/epoll设备的访问的封装(System Epoll)之后,这种现象得到了大大的缓解,如果说几个月前,大家还对epoll不熟悉,那么现在来说的话,epoll的应用已经得到了大范围的普及。

  那么究竟如何来使用epoll呢?其实非常简单。通过包含一个头文件 #include <sys/epoll.h> 以及几个简单的API将可以大大的提高你的网络服务器的支持人数。

  首先通过epoll_create(int maxfds)来创建一个epoll的句柄,其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄,之后的所有操作将通过这个句柄来进行操作。在用完之后,记得用close()来关闭这个创建出来的epoll句柄。

  之后在你的网络主循环里面,每一帧的调用epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:

  nfds = epoll_wait(kdpfd, events, maxevents, -1);

  其中kdpfd为用epoll_create创建之后的句柄,events是一个 epoll_event* 的指针,当epoll_wait这个函数操作成功之后,events里面将储存所有的读写事件。maxevents是当前需要监听的所有socket句柄数。最后一个timeout是epoll_wait的超时,为0的时候表示马上返回,为-1的时候表示一直等下去,直到有事件返回;为任意正整数的时候表示等这么长的时间,如果一直没有事件,则返回。一般如果网络主循环是单独的线程的话,可以用-1来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用0来保证主循环的效率。

epoll_wait范围之后应该是一个循环,遍利所有的事件:

    for(n = 0; n < nfds; ++n) {
            if(events[n].data.fd == listener) { //如果是主socket的事件的话,则表示有新连接进入了,进行新连接的处理。
                client = accept(listener, (struct sockaddr *) &local, &addrlen);
                if(client < 0){
                    perror("accept");
                    continue;
                }
                setnonblocking(client); // 将新连接置于非阻塞模式
                ev.events = EPOLLIN | EPOLLET; // 并且将新连接也加入EPOLL的监听队列。

  注意,这里的参数EPOLLIN | EPOLLET并没有设置对写socket的监听,如果有写操作的话,这个时候epoll是不会返回事件的,如果要对写操作也监听的话,应该是EPOLLIN | EPOLLOUT | EPOLLET

                ev.data.fd = client;
                if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
        // 设置好event之后,将这个新的event通过epoll_ctl加入到epoll的监听队列里面,这里用EPOLL_CTL_ADD来加一个新的epoll事件,通过EPOLL_CTL_DEL来减少一个epoll事件,通过EPOLL_CTL_MOD来改变一个事件的监听方式。
                    fprintf(stderr, "epoll set insertion error: fd=%d, client);
                    return -1;
                }
            }
            else // 如果不是主socket的事件的话,则代表是一个用户socket的事件,则来处理这个用户socket的事情,比如说read(fd,xxx)之类的,或者一些其他的处理。
                do_use_fd(events[n].data.fd);
       }

  对,epoll的操作就这么简单,总共不过4个API:epoll_create, epoll_ctl, epoll_wait和close。

  如果您对epoll的效率还不太了解,请参考我之前关于网络游戏的网络编程等相关的文章。

  世界变了,原来担心的问题,现在已经不是问题了。

本文乃网上搜集得来,其版权归原作者和原出处所有。如有侵犯版权之处请与我联系,我将马上进行处理。



相关专题:网络编程
epoll 效率测评
[转] Epoll用法举例说明

上一篇:Syn Flood 攻击(C 语言源代码)
下一篇:[转] Epoll用法举例说明

共有评论 2 条 网友评分 4分 查看全部评论

游客:nullget
评分:4
create_epoll(int maxfds) 应该是 epoll_create(int maxfds)
现在工作正在用这个,只对这个的效率有一个概念,具体有多快还不知道,能不能发些这方面的测试呢。
游客:antigloss
评分:0
谢谢提醒。已修正。
这里有个 epoll 效率评测
http://stdcpp.cn/html/8/8/0711/323.htm

查看全部评论

【发表评论】 评分:1分 2分 3分 4分 5分


验证码:

Powered By Www.Xydw.COM Ver1.14 管理
Copyright © 2005-2006 蚂蚁的 C/C++ 标准编程 All Right Reserved. XCMS
粤ICP备06014124号   站长:Antigloss