--poll of IO multiplexing

Source: Internet
Author: User

I. About POLL

For the IO multiplexing model, the advantage is that it eliminates the wait for one IO event to be ready, instead of detecting multiple IO data at the same time, when at least one of the waiting events is ready, it will return to tell the user that the process "has data ready, quickly see which one to deal with", For the implementation of IO multiplexing, in addition to the use of the Select function, another function still supports the multiplexed IO model, which is the poll function;


Two. Use of the poll function

Although there is also a wait for multiple IO events to be detected, the poll and select are somewhat different:

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M00/82/01/wKiom1dHB9mAvCb_AAAZZrdUWaM197.png "style=" float: none; "title=" Poll.png "alt=" Wkiom1dhb9mavcb_aaazzrduwam197.png "/>

function parameters,

First of all, this is the same as in the Select function parameter, which indicates the number of events currently being processed, which is the maximum value of +1 for the current file descriptor ( Nfds).

Timeout is also set to timeout time, just and select timeout is a struct not the same, here is just an integral type, and the meaning is milliseconds ;

and FDS is a struct pointer, as follows:

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M00/81/FF/wKioL1dHCM_xen90AAAdbbZXhd4736.png "style=" float: none; "title=" struct pollfd.png "alt=" Wkiol1dhcm_xen90aaadbbzxhd4736.png "/>

Structure,

FD Indicates the file descriptor to be cared for;

Events represents the event that the file descriptor cares about, which is an input parameter that tells the operating system what action events are concerned about the event that the file descriptor corresponds to, such as reading or writing;

revents is an output parameter that indicates that when poll returns, it tells the user what action event is ready, such as if Pollin is ready, then the value revent when returned is Pollin, Tells the user that the Pollin of the FD event is ready;

The values of events and revents can be as follows:

650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M02/82/00/wKioL1dHDDKzCxZ_AAAQQ7FNxqY876.png "title=" Pollin.png "alt=" Wkiol1dhddkzcxz_aaaqq7fnxqy876.png "/> Here to explain the options in fact not only these three, but here the discussion of these three options are the most commonly used;

Events is set to Pollin to indicate that the FD needs to read the data, and revents if the return pollin means that data is ready to read;

Similarly, events is set to Pollout to indicate the write of the data that is of interest to FD, while Revents returns pollout indicates that the write event is ready for the data to be written;

As for Pollpri, the latter explanation is set as an emergency option, and a Urg emergency pointer in the TCP protocol message is the first to start reading from the emergency data, and here is the meaning;


Three. Chestnut time

Similarly, you can use poll to write the server-side and client-side data communication based on the TCP protocol, as with select, and avoid using multiple-process and multi-threaded methods to wait for multiple IO interfaces:


Server-side:

#include  <stdio.h> #include  <stdlib.h> #include  <sys/types.h> #include  < sys/socket.h> #include  <netinet/in.h> #include  <arpa/inet.h> #include  <poll.h > #include  <unistd.h> #include  <string.h> #define  _backlog_ 5// Maximum number of waits in the network connection request queue #define _num_ 10//io event struct array size void usage (CONST&NBSP;CHAR&NBSP;*ARGV)// Error determination of command line parameters {    printf ("%s   [ip]   [port]\n", &NBSP;ARGV);     exit (0);} Static int createlistensocket (Int ip, int port)//Create a listening socket {    int  sock = socket (af_inet, sock_stream, 0);      if (sock  < 0)     {           perror ( "Socket");         exit (1);    }     &nbsp  struct sockaddr_in server;//set local network address information     server.sin_family =  af_inet;    server.sin_port = htons (port);     Server.sin_addr.s_addr = ip;     if (Bind (sock,  (struct sockaddr*) &server, sizeof (server))  < 0)//Binding     {            perror ("bind");         exit (2);     }        if (Listen (sock, _BACKLOG_)   &LT;&NBSP;0)//Monitor     {        perror ("Listen");         exit (3);    }     Return sock;} Int main (int argc, char *argv[]) {    if (argc != 3)           usage (argv[0]);     int port = atoi (argv[2]);  &NBSP;&NBSP;&NBSP;INT&NBSP;IP&NBSP;=&NBSP;INET_ADDR (argv[1]);     int listen_sock  = createlistensocket (Ip, port);//Get monitoring socket    struct sockaddr_in  client;//is used to store client-side network address information     socklen_t client_len = sizeof (client);     struct pollfd fds[_num_];//uses a struct array to hold various IO events     fds[0]. fd = listen_sock;//the listener socket into the array     fds[0].events = pollin;// Set the event required by the listener to read the data pollin    fds[0].revents = 0;    size_t  i = 1;    for (;  i < _num_; ++i)//Initialize member of struct array      {        fds[i].fd = -1;         fds[i].events = 0;        fds[i].revents = 0;     }    int max_fd = fds[0].fd;//set the maximum number of file descriptors      int timeout = 5000;//Setting Timeout time         while (1)     {        switch (Poll (fds, max_fd,  Timeout))         {             case -1://Error                  perror ("poll");                 break;             case 0://Timeout                  printf ("timeout...\n");                break;             default://at least one event is ready to operate IO data                  {                     size_t  i = 0;                     for (;  i < _num_; ++i)                      {                              //determine if a listener event is ready, if it represents a connection request to be processed             &Nbsp;            if ((Fds[i].fd == listen _sock)  &&  (Fds[i].revents == pollin)                          {                                  //Processing Connection                               int accept_sock = accept (listen_sock,  (struct  sockaddr*) &client, &client_len);                             if (accept_sock < 0)                              {                                  perror ("accept");                                  continue;                             }                              printf ("Connect with a client... [ip ]:%s  [port]:%d\N ",  inet_ntoa (CLIENT.SIN_ADDR),  ntohs (client.sin_port));                              size_t i = 0;                             // Will create a new data transfer socket file descriptor set into the poll structure array                              for (;  i  < _num_; ++i)                              {                           &nbsP;      if (fds[i].fd == -1)                                   {                                      fds[i].fd = accept_sock;                                      fds[i].events = pollin ;//Set the event to require reading data                                       max_fd  = fds[i].fd;//update maximum file descriptor number                                       break;                                  }                                                               }                             if (i == _num_)                                  close (Accept_sock);// If the number of the array is exceeded, the current cannot be processed, closed off                          }//is represented as other socket  for data transfer other than Listen socket                         else if (fds[i].fd > 0)  &&  (fds[i].revents  == pollin))                          {                              char buf[1024];                             //to read the data                               ssize_t size = read (fds[i].fd, buf, sizeof (BUF)-1);                              if (size < 0)//Read error                                   perror ("read");                              else&nbSp;if (size == 0)//client off, clear the corresponding position in the struct array                              {                                  printf ("client closed ... \ n ");                                 close (FDS[I].FD);                                  fds[i].fd = -1;                                  fds[i].events = 0;                                  fds[i].revents = 0;                              }                              else//read success, output data                              {                              &nBsp;   buf[size]  = ';                                  printf ("client# %s\n",  buf);                              }                         }                         else                          {}                      }                }                 break;         }    }    return 0;}

Client clients are not written here, and the client in socket programming based on TCP protocol is similar;


To run the program:

650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M02/82/0A/wKiom1dINs6TtO_ZAAAQyAzXPhg489.png "title=" Pollret.png "alt=" Wkiom1dins6tto_zaaaqyazxphg489.png "/>


Here's what you need to explain:

    1. Unlike select, select uses an Fd_set data type to hold the IO file descriptor for each operation, where the poll is a struct to hold the file descriptor and the event type of the lock concern, so poll does not handle the upper bound of the file descriptor, but the same is Each time the poll return still needs to traverse to get the event-ready location for the appropriate processing, or there is the additional overhead of replication and system traversal, which is still inefficient when handling more events;

    2. It is necessary to call the Fd_zero function for the fd_set of the corresponding event before each loop to the select to re-initialize the zeroing, because there is no new and closed file descriptor, it needs to be initialized and then re-set the event one by one into the corresponding fd_set. , and poll does not need to, because the use of a struct array to manage the equivalent of a combination of the settings in the Select array to hold the file descriptor and add the settings of the two steps, each time the poll will occur when the event is ready to the corresponding revents set, when the processing is completed by the system automatically attributed to 0, Manual initialization is not required to clear 0;

    3. Before a struct array is used, the struct member FD, events, and revents are random values, just like the variables defined, although they are then assigned valid values for later use. But in order to avoid the two semantic problems of judgment, it is best to initialize them to a uniform and recognizable invalid value before recycling.



Finish

This article is from the "Knock Code good Sleep zzz" blog, please be sure to keep this source http://2627lounuo.blog.51cto.com/10696599/1783922

--poll of IO multiplexing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.