Linux I / O reuse

Keywords: Linux

IO multiplexing: listen to multiple file descriptors at the same time

1.select

  • Interview frequency
  • What are the disadvantages of select and poll = > using epoll
  • epoll ET mode and LT mode

The focus is on the read event EPOLLIN, because the read event requires data in the buffer before it can be read, and if there is no data, it will be blocked. Therefore, it is necessary to judge whether there is data in the acceptance buffer first, and the write event (EPOLLOUT) can be written only if the buffer is empty

  1. select: listen to multiple file descriptors at the same time, up to 1024, read, write, exception and collection
    Kernel: polling mode
    Time complexity: O(n)
  2. poll: supports more file descriptors and more event types than select
    Kernel: polling mode
    Time complexity: O(n)
    Disadvantages of select and poll:
    -Finding ready descriptors requires traversing all descriptors O(n)
    -The kernel is polling
    -Descriptors and events need to be passed to the kernel each time
  3. epoll: solve the defects of select and poll
  1. select: the number of ready descriptors. I don't know who it is. If the number is small
    Read, write and exception events, up to 1024
    Check whether there is data within 5 seconds
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include <sys/time.h>
#include<sys/select.h>

int main()
{
   int fd = 0;//stdin 0 stdout 1 stderr 2 keyboard corresponding descriptor
   fd_set fdset;  //Collection descriptor detected by select
   while(1)
   {
      struct timeval tv = {5,0}; //Timeout
      FD_ZERO(&fdset); //Clear each bit in the collection
      FD_SET(fd,&fdset); //fd adding multiple data to the collection requires a loop
      
      int n = select(fd+1,&fdset,NULL, NULL,&tv); //Get the number of ready descriptors. It is impossible to know who found the data with descriptor 1 through the loop
             //fd+1 detects only the previous bits that may have data 
      if(n == -1)
      {
       printf("err \n"); //fail
       break;
      }
      if(n == 0)
      {
        printf("time out \n");//End of time
      }
      else
      {   //n> 0 has data
        if(FD_ISSET(fd,&fdset))  //success
        {
          char buff[128] = {0};
          read(fd,buff,127};    //Read data output
          printf("read:%s\n",buff);
        }
      }
   }
}
   

2. poll

  1. poll: listen for multiple file descriptors at the same time
    Support more file descriptors than select; Using arrays to implement

#include<poll.h>
POLLIN: shujukedu
Poll: Data writable
POLLRDHUP: the TCP connection is closed by the other party, or the other party has closed the write operation

Create socket:

136 int socket_init()         
137 {
138     int sockfd = socket(AF_INET,SOCK_STREAM,0);//Create socket
139     if(sockfd ==-1)
140     {
141          return -1;
142     }
143         //bind() can be bound, but generally not
144     struct sockaddr_in saddr;
145     memset(&saddr,0,sizeof(saddr));
146     saddr.sin_family = AF_INET;
147     saddr.sin_port = htons(6000);
148     saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
149 
150     int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
151     if(res == -1)
152     {
153         return -1;
154     }
155 
156     if(listen(sockfd,5) == -1)
157     {
158             return -1;
159     }
160 
161     return sockfd;
162 
163 
164 }
         

3. epoll

  1. epoll: it is suitable when there are many file descriptors
    Use a set of functions to implement

#include<sys/epoll.h>

  • epoll_create(): create a kernel event table. It is stored in the kernel space. It does not need to pass descriptors and events every time. The event is only passed to the kernel once. The data structure used by the event is a red black tree
  • epoll_ctl():
  • epoll_wait(): get ready descriptor

4. ET LT mode

  1. ET, LT mode
    ET epoll high efficiency mode edge trigger
    LT select poll epoll horizontal trigger

4.1 LT mode

  • LT mode

For example, when your mother calls for dinner, she calls once and continues to call until you eat


When the data entered by the client is hello, epoll_wait returns six times, one character at a time, and epoll when h is finished_ Wait will continue to send notifications until the entire data is read

4.2 ET mode

  • ET mode
  • There is no data loss in TCP protocol


For example, only one character can be processed at a time. If the data sent by the client is hello, only h will be processed for the first time, and the rest will be stored in the buffer until the next epoll_ When there is another event notification in wait, c will be output, which will be l next time;

  • In order to read all data in one event notification, the data needs to be read circularly
  • If you do not cycle, you can only read one at a time. When you cycle to read data, if recv reads the last empty, blocking will occur

#include<unistd.h>
#include<fcntl.h>

  • int fcntl(int fd,int cmd...) / / add non blocking attribute

  • After non blocking is set, the loop can be used to prevent blocking caused by empty data after reading
  • Using cycle can make epoll in ET mode_ All data can be read in one wait notification,
15 void setnonblock(int fd)  //Set non blocking property for fd
 16 {
 17         int oidfl = fcntl(fd,F_GETFL);
 18         int newfl = oidfl | O_NONBLOCK;
 19         if(fcntl(fd,F_SETFL,newfl) == -1)
 20         {
 21                 printf("fcntl err\n");
 22         }
 23 }

epoll_create idea: create a kernel event table

epoll_ctl(): adds a file descriptor to the kernel event table

5. libevent

libevent: commonly used in server-side programming, encapsulating poll and epoll

Define instance Base
Create event
Register (add) to libevent
The event loop starts to detect that the underlying call is select poll epoll_wait and other functions
Call the callback function fun() method with the ready event

win handle: file descriptor

Posted by helpmeplease2 on Sat, 20 Nov 2021 01:47:49 -0800