See an I/O performance issue today. I think about this question. Several common I/O analysis under Linux in this blog here
Analyzing blocking, non-blocking I/O, one thing in common is that many I/O are not able to confirm that I/O is ready and can only be polled by a single polling method, which is extremely inefficient when both ready and unprepared I/O are polled. asynchronous I/O, provides a way to prepare the I/O, will send a signal to the kernel, other time to continue to do other operations, this way a bad thing is that multiple I/O is ready at the same time, the signal sent bad processing, do not know that the signal corresponds to the descriptor.
So think, can there be a kind of I/O. Only the prepared I/O, unprepared I/O, and no operation are considered.
In fact, this I/O is multiplexed I/O. Before I can process I/O, we need to call the function to process the monitored I/O, judge Read and write events, wait for it to be ready to operate. These functions have SELECT, Pselect, poll, Epoll (Linux2.6 kernel post support).
First we look at the Select function, and we need to look at the passed arguments and the returned results respectively.
The function passed to select, mainly tells the kernel, we are interested in the descriptor, for each descriptor, we are concerned about the state, monitoring these I/O need to wait for how long.
When the Select function returns, we can know the number of descriptors that have been prepared, and for each of the three states of reading, writing, and exception, those descriptors are already available.
The prototype of the Select function is as follows:
#include <sys/select.h>
int Select (int maxfdp1,fd_set *restirct Readfds,
fd_set *restrict writefds,fd_ Set *restrict Exceptfds,
struct timeval *resttrict tvptr);
Here we need to explain the waiting time tvptr. (PS: Each pointer in the above parameter adds the keyword restrict, qualifying only the declared pointer to access the memory, and the other pointer accesses are not valid.) )
When the Tvptr==null,select function waits forever until it catches the monitor descriptor with a ready or an error signal, returns 1 if an error occurs, otherwise returns the number of ready-to-be descriptors;
When the tvptr->tv_sec==0 && tvptr->tv_usec==0,select function does not wait, the test all specified descriptors are returned immediately, getting the state of each descriptor, non-blocking I/O polling each descriptor;
When Tvptr->tv_sec!=0 | | The Tvptr->tv_usec!=0,select function waits for a specified time, and the timeout returns 0. Returns the number of prepared handles if there is a prepared handle within the waiting time. During the waiting time, the Select function can be interrupted by a signal.
The first parameter, MAXFDP1, means the maximum description of multibyte 1, so that you need to find the maximum descriptor in three sets, and then add one to the variable. In fact, this value can pass a default value, Fd_setsize, which is a constant of the kernel maintenance, its value is generally 1024, indicating that the SELECT function can handle a maximum number of descriptors of 1024. You can modify this parameter if you want the kernel to support more.
Then, we continue to look at the function, there are three parameters need to note Readfds, Writefds, Exceptfds, these three are in a readable, writable, unusual handle of the collection, these handles are stored in a called Fd_set data type. Now look at the four basic operations on this set:
#include <sys/select.h>
int fd_isset (int fd,fd_set *fdset);
void fd_set (int fd,fd_set *fdset);
void fd_clr (int fd,fd_set *fdset);
void Fd_zero (Fd_set *fdset);
First, look at the first function, fd_isset the function is used to test if the handle FD is within Fdset, if it returns a non-0 value, then returns 0 if it is not. Fd_set adds a handle FD to the collection Fdset, FD_CLR clears the handle Fd,fd_zero from the collection Fdset, initializes the collection Fdset, Make each location 0. In the past, add parameters to the Select function as an example to learn more about the process of the next operation, you can see the following code:
Fd_set Readset,writeset;
Fd_zero (&readset);
Fd_zero (&writeset);
Fd_set (0,&readset);
Fd_set (3,&readset);
Fd_set (2,&writeset);
Fd_set (4,&writeset);
Fd_set (1,&writeset);
Select (5,&readset,&writeset,null,null);
Below is Pselect, this is an upgrade version of Select, provides finer timing operation and signal shielding Word, function prototype as follows:
int pselect (int maxfdp1,fd_set *restirct Readfds,
fd_set *restrict writefds,fd_set *restrict Exceptfds,
const struct TIMESPEC *resttrict tsptr,const sigset_t *restrict sigmask);
The difference between this function and select is that the timer is changed from Timeval to Timespec, which is more granular and can be precise to the microsecond level. There is also a signal shielding word sigmask. The signal shielding Word can be installed atomically, and the previous signal screen word is restored when the function returns. about how to set the signal screen word, you can look at this blog.
All of the above is the full understanding of the Select function.
Let's look at another function, called poll.
The poll function originates from the system V,poll function and is closely related to stream systems. Its function prototype is as follows:
#include <poll.h>
int poll (struct POLLFD fdarray[],nfds_t nfds,int timeout);
Poll is different from select, select adds descriptors to a collection by state, poll forms an array of POLLFD structures, and each element in the array specifies a descriptor number and the state to which it is concerned.
struct pollfd{
int fd;
Short events;
Short revents;
};
The number of elements in the Fdarray is determined by Nfds. Events in the struct tell the kernel what to look for in this descriptor, and revents is the return value after the kernel operation to illustrate what the kernel does with that descriptor.
When a descriptor is hung off, the data cannot be written to the descriptor, but the data of the file descriptor can be read.
The last timeout of the poll function, when 1, waits forever until the signal is captured, poll returns-1. Returns the number of prepared file descriptors if the specified descriptor is ready. When 0 is not waiting, all descriptors are tested and returned, and all descriptors are processed as nonblocking polling. When timeout is greater than 0, wait for timeout milliseconds, the timeout returns 0, otherwise the number of prepared is returned.
The last Epoll way, you can look at this blog before the summary: Epoll