Multiplexer poll


  • Like select, poll is also a ready event notification scheme. Poll has only one function, that is, waiting.
  • Poll solves two select problems: there is no upper limit on the file descriptor that poll waits for.
  • poll separates the input and output using variables. Therefore, each cycle does not need to be added again.

Introduction to poll function

 #include <poll.h>
 int poll(struct pollfd *fds, nfds_t nfds, int timeout);     

The first parameter, fds, is an array of structures, because array participants degenerate into pointers.

struct pollfd {
               int   fd;         /* file descriptor */
               short events;     /* requested events */
               short revents;    /* returned events */

  • fd represents the file descriptor you want to monitor.
  • Events is what the user tells the kernel, which represents what events you want the operating system to monitor for you.
  • Events means that the kernel tells the user which events of the file descriptor are ready on behalf of the operating system.
  • pollfd separates the input and output parameters. Each time a new fd is added, the old array does not need to be changed. Reduces the polling process.

Second parameter:
nfds represents the number of fd.

Third parameter:

  • Represents the time you want to wait for poll blocking once. The unit is milliseconds. After the time expires, it will timeout and return, just like select.
  • timeout is set to 0, indicating poll non blocking wait.
  • timeout is set to - 1, indicating blocking wait.

Return value:

  • The return value is exactly the same as that of select.

Event settings

  • There are many events in events and events.
  • Here are two, POLLIN and POLLOUT. Stands for read ready and writable ready, respectively.
  • The method used here is similar to that of the open function. Because events is of type short, each bit of short represents an event. We use bitwise or to add events so that we can monitor different events in an fd at the same time.
  • We use bitwise and to detect events.

Use poll

Monitoring standard input:

  1 #include <iostream>
  2 #include <poll.h>
  3 #include <cstdlib>
  4 #include <unistd.h>
  6 using namespace std;
  8 int main(){
  9   //int poll(struct pollfd *fds, nfds_t nfds, int timeout);                                          
 10   struct pollfd fds[1];
 11   fds[0].fd = 0;
 12   fds[0].events = POLLIN;
 13   fds[0].revents = 0; //Events can be set by the kernel without setting.
 15     char buf[1024] = {0};
 16   for(;;){
 17     cout << "poll begin..." << endl;
 18     int ret = poll(fds, 1, 1000);  //The unit of timeout is milliseconds!
 19     if(ret < 0){
 20       cerr << "poll error" << endl;
 21       exit(1);
 22     }
 23     else if(ret == 0){
 24       cout << "timeout..." << endl;
 25       continue;
 26     }
 27     else{
 28         ssize_t ss = read(0, buf, sizeof(buf) - 1);
 29         buf[ss] = 0;
 30         cout << "echo # "<< buf << endl;
 31     }
 32   }

  • If you change monitoring POLLIN to monitoring POLLOUT, the poll begin will always be printed because the output buffer is always empty and there is always space. Reading is to see whether there is data, and writing is to see whether there is space.

Pseudo code of poll:

struct polllfd fds[MAX];  //The value of MAX is set by you;
//fds[i].fd is initialized to a negative number to identify that it is not used!
fds[0].fd = lsock;
fds[0].events = POLLIN;

	poll(fds, MAX, 1000);
	for(int i = 0; i < MAX; ++i){
		if(fds[i].fd == FLAG) //FLAG is the negative number you set, indicating that the location is not used
		else if(fds[i].events & POLLIN) //Multiple events can also be detected here,
			if(fds[i].fd == lsock) //connect
				sock add to fds; //If yes, join the fds, and then set the events you want to detect.
				sock add events
			{/** Processing data**/}
		else if(fds[i].events & POLLOUT) //Handle write events with the same logic as above!
		{/* slightly */}

Advantages and disadvantages of poll

  • Compared with select, poll does not need to do more polling detection.
  • The file descriptor detected by poll has no upper limit.


  • Still can not avoid the user to kernel, kernel to user data copy.
  • Although users do not poll too much, polling detection should still be used in the kernel, so that the efficiency will still decline after there are more file descriptors.


Do not multiplex:

  • Multiplexing is not applicable in any case, depending on the scenario.
  • Multiplexer is suitable for long connection and long distance communication. This kind of scenario has a large proportion of waiting time.
  • That is, multi-channel switching is to reduce the proportion of waiting. If the waiting time is small, then multi-channel switching is of little significance. Not even as good as other IO models.
  • At this time, polling or copying of multiplexing will consume resources, far more than waiting resources.

The upper layer protocol shall also be considered for multiplexing:

  • Multiplexing only ensures that the data is higher than the water mark, but does not guarantee the integrity of the data.
  • For example, you want 1024 bytes of http message, but the multiplexer will notify you when it receives 100 bytes. Then you need to save 100 bytes of data first, then reset the file descriptor into the array and continue to wait.
  • After waiting, 1024 bytes are parsed, and then a response is generated, which is inserted into the multiplexer by writing events, and then sent out.

Tags: Linux computer networks io poll

Posted on Fri, 03 Dec 2021 23:43:14 -0500 by 2DaysAway