Five IO models and select multiplexing IO model

Table of contents

1. Typical IO model

 1.1 Blocking I/O

1.2 Non-blocking I/O

1.3 Signal driving I0

1.4 IO multiplexing

 1.5 Asynchronous I/O

The role and significance of multiplexing

2. Multiplexing IO model (select)

2.1 Interface

 2.2 Event collection in the interface: fd_set

2.2 The way select uses the event collection (bitmap)

2.2.1 Interface

2.3 How to use select:

2.4 The return value of select: (a bit anti-human)

2.5 select test code:

3. Use select to implement a single thread to receive multiple clients


1. Typical IO model

 1.1 Blocking I/O

Before the kernel prepares the data, the system call will wait until the data arrives, and the IO call will not return until the data is copied.

  • 1.2 Non-blocking I/O

  • If the kernel has not prepared the data yet, the system call will still return directly and return the EWOULDBLOCK error code. The return of non-blocking IO needs to judge the return value of the system call function to judge whether the current function has completed the IO function.
  • 1. Not completed: Generally, it will continue to call with a loop (the IO function is not completed), but this is also a huge waste of CPU resources.
  • 2. Finished: the kernel has prepared the data and copied it back (the IO function is completed)

  • 1.3 Signal driving I0

  • (Like a bell on a fishing rod)
  • When the kernel prepares the data, it uses the SIGIO signal to notify the application to perform the I0 operation. Here, for example, our processing of zombie processes (zombie processes means that the child process exits before the parent process, and no one recycles the exit information of the child process) can cooperate with the signal. When the child process exits, we can customize the signal processing method. Call the wait function to recycle the child process

  • 1.4 IO multiplexing

  • Let's first look at a scenario

The above brainless method of creating processes and threads cannot handle a large number of clients . So how to solve it?

Multiplexing is required

The multi-way transfer IO model can help us monitor multiple file descriptors at the same time

 With multi-way transfer, you don't need to create threads or processes without thinking

It's like hiring someone to go fishing when fishing. If a fishing rod catches a fish, let him not move, and we can enjoy the pleasure of pulling the fish up.

  •  1.5 Asynchronous I/O

  • When the data copy is completed, the kernel notifies the application program (and the signal driver tells the application program when to start copying data). For example, fishing, signal IO is equivalent to helping a bell on the fishing rod. When the bell rings, it will notify you to put away the fishing rod and then fish. Asynchronous IO is to help you fish, that is, to help you find someone to be He will call you to pick up the fish after he has prepared the fish

 The biggest difference between synchronous IO and asynchronous IO is:

Asynchronous IO doesn’t care about anything, just tell you that I’m going to do this thing, and the next thing is up to you (how long is your business), and you will tell me when you’re done

The role and significance of multiplexing

1. Function: IO multi-transfer can help us wait for the ready status of multiple file descriptors, and the multi-transfer IO model can help us monitor multiple file descriptors at the same time

 2. The multi-channel transfer IO model is the basis for high program concurrency

High concurrency:   the program can handle a large number of client requests

3. Expansion: A good program needs to consider high concurrency and high availability

High availability: It means that no matter what bad scenarios the program encounters, it can be used, such as the program hangs up (backup process) (daemon process)

2. Multiplexing IO model (select)

  • 2.1 Interface

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

nfds: The value is the value of the largest file descriptor + 1, and its function is to control the polling monitoring range of select.

  • fd_set: event collection
  • readfds : read event collection
  • writefds: write event collection
  • exceptfds: collection of abnormal events

timeout :   Indicates the way of working

  • Blocking method: NULL
  • non-blocking: 0
  • Monitoring with timeout: pass a structure object like struct timeval

  • return value:
  • Success : returns the number of ready file descriptors
  • Failure : return -1, and set errno, the programmer can use the perror function to check the cause of the failure

 2.2 Event collection in the interface: fd_set

 first impression:

        fd_set: It is a structure, and there is an array in the structure, the name is fds_bits

Explore:

  • 1. What is the element type of the data?
  • 2. What is the number of elements in the data?

 We can find that the size of the array is only 16, which is very strange. If an element stores a file descriptor value, there are only 16 at most. There will be many file descriptors.

So what is going on?

The use of event collection is not used in the form of an array , but in the form of bits (bitmaps)

2.2 The way select uses the event collection (bitmap)

2.2.1 Interface

  • void FD_CLR(int fd,fd_set *set) ;
    • Function: remove fd from the event set set, the essence is to set the bit position corresponding to fd to 0
  • int FD_ISSET(int fd,fd_set *set) ;
    • Function: To judge whether the fd file descriptor is in the set collection, the essence is to judge whether the bit corresponding to fd is 0
    • return value:
    • 0: Indicates that fd is not in the set
    • 1: Indicates that fd is in the set
  • void FD_SET(int fd,fd_set *set) ;
    • Function: Set the fd file descriptor to the set event collection, the essence is to set the bit corresponding to fd to 1
  • void FD_ZERO(fd_set *set) ;
    • Function: Clear the event collection. The essence is to set all the bits in the set to 0

example:

  • 2.3 How to use select:

  • 1..select has three event sets: read event set, write event set, and exception event set.
  • 2. When it is necessary to pay attention to a certain event of a certain file descriptor, add the next file descriptor to the corresponding event collection. For example: pay attention to (the read event of file descriptor 0, then add file descriptor 0 to the read event set readfds.
  • 3. If you do not pay attention to certain events, pass NULL when passing parameters to select.

  • 2.4 The return value of select: (a bit anti-human)

  • 1. The return value is the number of ready file descriptors
  • 2. The ready file descriptor is stored in the event collection and returned to the caller

But: what about no file descriptors ready? Is it also placed in the event collection?

Certainly not, because after the event collection is successfully completed by select monitoring, it is still necessary to judge which file descriptors are ready. In order to be able to judge, it is necessary to remove the unready ones

 Therefore, if the select monitoring is successful, when monitoring is needed again, the file descriptor that was not ready last time needs to be put in the event collection for him

  • 2.5 select test code:

code:

 

 

 Before, it was blocked in scanf waiting for reading process. Let's see where select is used for monitoring. Where is this process blocked:

  • 3. Use select to implement a single thread to receive multiple clients

  • We know that if there is no multi-way transfer io, then multi-threading must be used to handle receiving multiple clients connecting to the server. So here we can use one thread to receive connections from multiple clients.

Transformation of the former:

        accept is placed outside the while loop, this process can only receive one client connection for a lifetime

        accept is placed outside the while loop, this process can only contact the client once in a lifetime (but can send data with multiple clients)  

After transformation:

        Idea: select helps us monitor listen_sockfd (one), new_sockfd (multiple)

                   When the select monitoring is successful, we make different operations for different file descriptors

                   listen_sockfd (read event): accept

                   new_sockfd (read event): recv     

Server:

Kefuduan:

 Run it to observe the results:

 It can be seen that one thread can handle polymorphic clients, which is really amazing! ! !

Fourth, the advantages and disadvantages of select

4.1 Advantages:

4.2 Disadvantages

 

Guess you like

Origin blog.csdn.net/flyingcloud6/article/details/129109180