epoll

 epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait。Linux-2.6.19又引入了可以屏蔽指定信号的epoll_wait: epoll_pwait。至此epoll家族已全。其中epoll_create用来创建一个epoll 文件描述符 ,epoll_ctl用来添加/修改/删除需要侦听的文件描述符及其事件,epoll_wait/epoll_pwait接收发生在被侦听的描述符上的,用户感兴趣的IO事件。epoll 文件描述符 用完后,直接用close关闭即可,非常方便。事实上,任何被侦听的文件符只要其被关闭,那么它也会自动从被侦听的 文件描述符 集合中删除,很是智能。
  每次添加/修改/删除被侦听 文件描述符 都需要调用epoll_ctl,所以要尽量少地调用epoll_ctl,防止其所引来的开销抵消其带来的好处。有的时候,应用中可能存在大量的 短连接 (比如说Web服务器),epoll_ctl将被频繁地调用,可能成为这个系统的瓶颈。
  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, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:
  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范围之后应该是一个循环,遍历所有的事件:
  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、付费专栏及课程。

余额充值