epoll_pool_select

来源:互联网 发布:电压力锅 知乎 编辑:程序博客网 时间:2024/06/01 23:14

1.Epoll

 常用操作:
  #include <sys/epoll.h>

 1,1 int epoll_create(int size);
  返回值:On  success,  these system calls return a non-negative file descriptor.
  
  
  
 1.2 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  返回值:When  successful,  epoll_ctl()  returns 0.
      
  这个函数通过之前创建的epfd来控制epoll,需要一些操作类型码(op),来控制目标的描述符。
  This  system  call  performs  control  operations on the epoll instance
        referred to by the file descriptor epfd.  It requests that  the  operation op be performed for the target file descriptor- fd.
        
  
  Valid values for the op argument are :
   
       EPOLL_CTL_ADD
              Register  the  target  file  descriptor fd on the epoll instance
              referred to by the file descriptor epfd and associate the  event
              event with the internal file linked to fd.

        EPOLL_CTL_MOD
              Change  the event event associated with the target file descrip-
              tor fd.

        EPOLL_CTL_DEL
        
  //////////////////////////////////////////////////////////////////////////
    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 */
           };
          
  The  events  member is a bit set composed using the following available event types:
        
        EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
  EPOLLOUT:表示对应的文件描述符可以写;
  EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
  EPOLLERR:表示对应的文件描述符发生错误;
  EPOLLHUP:表示对应的文件描述符被挂断;
  EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
  EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

  
        
   1.3  int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
   
   返回值:
    When  successful,  epoll_wait()  returns the number of file descriptors
       ready for the requested I/O, or zero if no file descriptor became ready
       during  the  requested  timeout  milliseconds. 
      
       //描述
       The epoll_wait() system call waits for events  on  the  epoll  instance
       referred to by the file descriptor epfd.  The memory area pointed to by
       events will contain the events that will be available for  the  caller.
       Up  to  maxevents are returned by epoll_wait().  The maxevents argument
       must be greater than zero.

       The call waits for a maximum time of timeout milliseconds.   Specifying
       a  timeout of -1 makes epoll_wait() wait indefinitely, while specifying
       a timeout equal to zero makes epoll_wait() to return  immediately  even
       if no events are available (return code equal to zero)
       
  示例代码:
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <unistd.h>
  #include <sys/epoll.h>
  #include <sys/types.h>       
  #include <sys/socket.h>
  #include <errno.h>
  
  int main()
  {
      int socketfd, ret, i;
       
      socketfd = socket(AF_INET,SOCK_STREAM,0);
      if(socketfd == -1)
      {
       perror("func socket\n");
       exit(0);
      }
    
      struct sockaddr_in srvaddr;
     
      srvaddr.sin_family = AF_INET;
      srvaddr.sin_port = htons(8001);
      srvaddr.sin_addr.s_addr = inet_addr("192.168.1.103");
     
      if(bind(socketfd,(struct sockaddr*)&srvaddr,sizeof(srvaddr))<0)
      {
       perror("func bind\n");
       exit(0);
      }
     
      if(listen(socketfd,SOMAXCONN)<0)
      {
       perror("func listen\n");
       exit(0);
      }
     
      struct epoll_event ev,events[20];
      int epollfd, nfds;
     
      struct sockaddr_in peeraddr;
      socklen_t peerlen = sizeof(peeraddr);
     
      char revbuf[1024] = {0};
      unsigned int connfd;
     
      epollfd = epoll_create(100);
  
      ev.data.fd = socketfd;
     
      ev.events = EPOLLIN|EPOLLET;
     
      epoll_ctl(epollfd,EPOLL_CTL_ADD,socketfd,&ev);
     
      while(1)
      {
    nfds = epoll_wait(epollfd, events, 20, 500);
    
    
                              
          for(i=0; i<nfds; i++)
    {
           if (events[i].data.fd == socketfd) {
                        
                 connfd = accept(socketfd,(struct sockaddr*)&peeraddr,
                       (socklen_t*)&peerlen);
                 if (connfd == -1) {
                    printf("accept");
                     exit(0);
                 }
                
                 printf("child process socketfd:%d, connfd%d\n",socketfd,connfd);
   
           printf("peeradd:%s \npeerport:%d\n",inet_ntoa(peeraddr.sin_addr),
                    ntohs(peeraddr.sin_port));
             
                 ev.events = EPOLLIN | EPOLLET;
                 ev.data.fd = connfd;
                 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd,
                     &ev) == -1) {
                     perror("epoll_ctl: conn_sock");
                     exit(EXIT_FAILURE);
                 }
              }else if(events[i].events & EPOLLIN){
                
                  ret = read(events[i].data.fd,revbuf,sizeof(revbuf));
      
         if(ret == 0)
         {
             printf("clt close \n");
             //exit(0);
         }
         
         fputs(revbuf,stdout);
         //memset(revbuf,0,sizeof(revbuf)); 
              } 
      
          }    
    }
      return 0;
  }

 
2.poll

    #include <poll.h>

       int poll(struct pollfd *fds, nfds_t nfds, int timeout);
      
      
        struct pollfd {
               int   fd;         /* file descriptor */
               short events;     /* requested events */
               short revents;    /* returned events */
           };
          
    The field fd contains a file descriptor for an open file.

       The  field  events  is  an  input  parameter, a bit mask specifying the
       events the application is interested in.

       The field revents is an output parameter, filled by the kernel with the
       events  that  actually  occurred.
      
      
           POLLIN There is data to read.

              POLLPRI
                     There is urgent data to read (e.g., out-of-band  data  on
                     TCP  socket;  pseudo-terminal  master  in packet mode has
                     seen state change in slave).

              POLLOUT
                     Writing now will not block.

              POLLRDHUP (since Linux 2.6.17)
                     Stream socket peer closed connection, or shut down  writ-
                     ing  half  of  connection.   The _GNU_SOURCE feature test
                     macro must be defined in order to obtain this definition.

             POLLERR
                     Error condition (output only).

              POLLHUP
                     Hang up (output only).

              POLLNVAL
                     Invalid request: fd not open (output only).

            When  compiling with _XOPEN_SOURCE defined, one also has the following,
            which convey no further information beyond the bits listed above:

              POLLRDNORM
                     Equivalent to POLLIN.

              POLLRDBAND
                     Priority band data  can  be  read  (generally  unused  on
                     Linux).

              POLLWRNORM
                     Equivalent to POLLOUT.

              POLLWRBAND
                     Priority data may be written.
  
    返回值:
       On success, a positive number is returned; this is the number of struc-
       tures  which  have  non-zero  revents  fields  (in  other  words, those
       descriptors with events or errors reported).  A value  of  0  indicates
       that  the call timed out and no file descriptors were ready.  On error,
       -1 is returned, and errno is set appropriately.
      
3.select
 
 #include <sys/select.h>

       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);
 
 
 返回值:
   On  success,  select()  return the number of file descriptors contained
    in the three returned  descriptor  sets  (that  is,  the total  number 
    of  bits  that  are set in readfds, writefds, exceptfds)which may be zero
    if the timeout expires  before  anything  interesting happens.
     
         On error, -1 is returned, and errno is set appropriately; the
       sets and timeout become undefined, so do not  rely  on  their  contents
       after an error.
      
 NOTE:
    nfds  is the highest-numbered file descriptor in any of the three sets,
       plus 1.

   struct timeval {
               long    tv_sec;         /* seconds */
               long    tv_usec;        /* microseconds */
           };
    

示例代码:
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int main(void)
       {
           fd_set rfds;
           struct timeval tv;
           int retval;

           /* Watch stdin (fd 0) to see when it has input. */
           FD_ZERO(&rfds);
           FD_SET(0, &rfds);
     /* Wait up to five seconds. */
           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);
           /* Don’t rely on the value of tv now! */

           if (retval == -1)
               perror("select()");
           else if (retval)
               printf("Data is available now.\n");
               /* FD_ISSET(0, &rfds) will be true. */
           else
               printf("No data within five seconds.\n");

           exit(EXIT_SUCCESS);
       }