epoll 使用小結

瞭解一下

Epoll 是一種高效的管理socket的模型,相對於select和poll更加高效。數組

數據結構

  • sys/epoll.h
typedef union epoll_data {
                void ptr;
                int fd;
                __uint32_t u32;
                __uint64_t u64;
      } epoll_data_t;

      struct epoll_event {
                __uint32_t events;    / Epoll events /
                epoll_data_t data;    / User data variable /
      };

(1) epoll_data 聯合體用來保存觸發事件的某個文件描述符相關的數據.數據結構

(2) epoll_event 結構體的events字段是表示感興趣的事件和被觸發的事件:socket

EPOLLIN :表示對應的文件描述符能夠讀;
EPOLLOUT:表示對應的文件描述符能夠寫;
EPOLLPRI:表示對應的文件描述符有緊急的數據可讀
EPOLLERR:表示對應的文件描述符發生錯誤;
EPOLLHUP:表示對應的文件描述符被掛斷;
EPOLLET:表示對應的文件描述符設定爲edge模式

函數

*epoll_create, epoll_create1 函數
函數聲明:int epoll_create(int size)
該函數生成一個epoll專用的文件描述符,其中的參數是指定生成描述符的最大範圍。函數

  • epoll_ctl函數

函數聲明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event event) 該函數用於控制某個文件描述符上的事件,能夠註冊事件,修改事件,刪除事件。
參數:epfd:由 epoll_create 生成的epoll專用的文件描述符;
op:要進行的操做例如註冊事件:ui

EPOLL_CTL_ADD 註冊、
EPOLL_CTL_MOD 修改、
EPOLL_CTL_DEL 刪除
  • epoll_wait函數
    函數聲明: int epoll_wait(int epfd,struct epoll_event events,int maxevents,int timeout) 該函數用於輪詢I/O事件的發生;
    參數:
    epfd: 由epoll_create 生成的epoll專用的文件描述符;
    epoll_event: 用於回傳代處理事件的數組;
    maxevents: 每次能處理的事件數;
    timeout: 等待I/O事件發生的超時值(ms);-1永不超時,直到有事件產生才觸發,0當即返回。返回發生事件數。-1有錯誤。

Sample:

int main()
{
    //聲明epoll_event結構體的變量,ev用於註冊事件,數組用於回傳要處理的事件
    struct epoll_event ev,events[20];

    epfd=epoll_create(10000); //建立epoll句柄
   
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    //把socket設置爲非阻塞方式
    setnonblocking(listenfd);
   
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_port=htons(SERV_PORT);
    bind(listenfd,(struct sockaddr )&serveraddr, sizeof(serveraddr));
    listen(listenfd, 255);

    //設置與要處理的事件相關的文件描述符
    ev.data.fd=listenfd;
    //設置要處理的事件類型
    ev.events=EPOLLIN;
    //註冊epoll事件
    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);

    for ( ; ; )
    {
      //等待epoll事件的發生
      nfds=epoll_wait(epfd,events,20,1000);
      //處理所發生的全部事件
      for(i=0;i<nfds;++i)
      {
         if(events .data.fd==listenfd)
         {
                connfd = accept(listenfd,(struct sockaddr )&clientaddr, &clilen);
                if(connfd<0)
                {
                  perror("connfd<0");
                }
                setnonblocking(connfd);
                //設置用於讀操做的文件描述符
                ev.data.fd=connfd;
                //設置用於注測的讀操做事件
                ev.events=EPOLLIN|EPOLLET;
                //註冊event
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
         }
         else if(events .events&EPOLLIN)
         {
                read_socket(events .data.fd);
                ev.data.fd=events .data.fd;
                ev.events=EPOLLIN|EPOLLOUT|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
         }
         else if(events .events&EPOLLOUT)
         {
                write_socket(events .data.fd);
                ev.data.fd=events .data.fd;
                ev.events=EPOLLIN|EPOLLET; //ET模式
            epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
         }
         else
         {
                perror("other event");
         }
      }
    }
}
相關文章
相關標籤/搜索