对epoll总结

来源:互联网 发布:java终止for无限循环 编辑:程序博客网 时间:2024/04/30 13:23

    epoll是Linux特有的I/O复用函数(个人通过搜索资料和听老师讲解认为epoll相较于select和poll要更加优秀)。

    epoll与poll和select的区别是他是用一组函数完成的任务而不是单个函数。

    epoll把用户关心的文件描述符上面的事件放在内核里的一个时间表上,故epoll需要一个额外的文件描述符,来唯一标识这个时间表。

     #include <sys/epoll.h>

     int epoll_create(int size);

     size给内核提示事件表需要多大。该函数返回的文件描述符将用作其他epoll函数调用的第一个参数,以指定要访问的内核事件表。

   

     #include <sys/epoll.h>

     int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event)

     epfd是上面一个epoll_create的返回值

     fd表示要操作的文件描述符

     op指定操作类型    EPOLL_CTL_ADD 往事件表中注册fd上的事件

                                  EPOLL_CTL_MOD修改fd上的注册事件

                                  EPOLL_CTL_DEL删除fd上的注册事件

     event指定事件,表示他的宏就是在poll前面加上E,这里不做列举。

     

    #include <sys/epoll.h>

    int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);

    成功则返回就绪文件描述符的个数,失败返回-1。

    timeout与poll相同

    maxevents指定最多监听多少个事件,必须大于0

    

    epoll的两种模式   LT ET

    LT:默认工作模式,仅仅相当于一个较高效的poll。

    ET:epoll的高效模式,实现方法是往epoll内核时间表中注册一个文件描述符上的EPOLLET事件。

    

    LT:通知一次,如果你不进行处理那么就一直通知下去。

    ET:通知一次,不处理后续的epoll_wait也不会再次的去通知。

    由于ET降低了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。   


关于epoll监听其他进程的代码

#include <sys/epoll.h>
#include <sys/socket.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>




void setnonblock(int fd)
{
    int s_flg = fcntl(fd,F_GETFL);
    int t_flg = s_flg|O_NONBLOCK|EPOLLRDHUP;
    fcntl(fd,F_SETFL,t_flg);
}


void fd_del(int epfd,int fd)
{
          if(epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL)==-1)
          {
              perror("epollctl del error");
          }
}




int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd!=-1);


    struct sockaddr_in saddr,caddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6500);
    saddr.sin_addr.s_addr = inet_addr("192.168.1.11");


    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    assert(res!=-1);


    listen(sockfd,5);


    int epfd = epoll_create(1);//I just need one.只监听一个事件
    assert(epfd!=-1);


    struct epoll_event ev;
    ev.events = EPOLLIN|EPOLLET;//open ET
    ev.data.fd = sockfd;
    int a = epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ev);//add,开始监听sockfd这个描述符的变化
    assert(a!=-1);
    setnonblock(sockfd);


    struct epoll_event evs;


    while(1)
    {
         int n = epoll_wait(epfd,&evs,1,0);
         int fd = evs.data.fd;
         if(n==-1)
         {
             perror("epoll_wait error!\n");
             continue;
         }
         //because the timeout is 0 so do not do anything when the n is 0
         if(n>0)
         {
             if(evs.events&EPOLLRDHUP)
             {
                  fd_del(epfd,fd);
                  close(fd);
                  printf("client RDHUP over!\n");
                  continue;
             }
             if(evs.events&EPOLLIN)
             {


                  if(fd==sockfd)//监听到了有新的客户端请求链接
                  {
                      int len = sizeof(caddr);
                      int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
                      if(c<0)
                      {
                          continue;
                      }
                      struct epoll_event ev2;
                      ev2.events = EPOLLIN|EPOLLET|EPOLLRDHUP;
                      ev2.data.fd = c;
                      epoll_ctl(epfd,EPOLL_CTL_ADD,c,&ev2);//链接成功开始监听这个链接的变化
                      setnonblock(c);
                  }
                  else
                  {
                  while(1)//这里只考虑了对面发送信息的变化和断开连接的变化
                  {
                      char buff[128] = {0};
                      int num = recv(fd,buff,127,0);
                      if(num==0)
                      {
                             fd_del(epfd,fd);
                             close(fd);
                             printf("one client over\n");
                             break;
                      }
                      else
                      {
                           printf("%s",buff);
                      }


                  }




             }


         }


    }
   }
    return 0;
}


相应客户端和上两篇文章的客户端一致,关于epoll会用高效模式就好了,低效的你可以了解,毕竟用的时候肯定会更喜欢效果卓越的用法。

http://www.cnblogs.com/zhangmo/archive/2013/04/02/2995645.html

epoll之所以高效的原因

http://blog.csdn.net/russell_tao/article/details/7160071


0 0
原创粉丝点击