epoll-linux提高并发服务器效率

在大家苦苦的为在线人数的增长而导致的 系统资源吃紧上的问题正在发愁的时候,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, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:
1
nfds = epoll_wait(kdpfd, events, maxevents, -1);
其中kdpfd为用epoll_create创建之后的句柄,events是一个epoll_event*的 指针,当epoll_wait这个函数操作成功之后,epoll_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket 句柄数。最后一个timeout是epoll_wait的超时,为0的时候表示马上返回,为-1的时候表示一直等下去,直到有事件范围,为任意正整数的时候表示等这么长的时间,如果一直没有事件,则返回。一般如果网络主循环是单独的线程的话,可以用-1来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用0来保证主循环的效率。
epoll_wait范围之后应该是一个循环,遍历所有的事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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=%d0, client);
             return -1;
         }
    } else if (event[n].events & EPOLLIN) {   // 如果是已经连接的用户,并且收到数据,
                                              // 那么进行读入
         int sockfd_r;
         if ((sockfd_r = event[n].data.fd) < 0)
             continue ;
         read(sockfd_r, buffer, MAXSIZE);
         // 修改sockfd_r上要处理的事件为EPOLLOUT
         ev.data.fd = sockfd_r;
         ev.events = EPOLLOUT | EPOLLET;
         epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_r, &ev)
    } else if (event[n].events & EPOLLOUT) { // 如果有数据发送
         int sockfd_w = events[n].data.fd;
         write(sockfd_w, buffer, sizeof (buffer));
         // 修改sockfd_w上要处理的事件为EPOLLIN
         ev.data.fd = sockfd_w;
         ev.events = EPOLLIN | EPOLLET;
         epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_r, &ev)
    }
    do_use_fd(events[n].data.fd);
}
对,epoll的操作就这么简单,总共不过4个API:epoll_create, epoll_ctl, epoll_wait和close。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值