Select, poll, and Epoll are the mechanisms of IO multiplexing, but their mechanisms are very different.
1. Select
At the beginning of the select mechanism, it is necessary to copy the Fd_set from the user space to the kernel space, and the number of FD detected is limited, set by fd_setsize, typically 1024.
When testing, according to timeout, traversing the Fd_set table, the active FD (can read or write or error), copied to the user space,
Then the related FD is processed in the user space in turn.
This mechanism is a very early version of the Linux kernel, Epool is based on the Select,pool based on optimization, the disadvantages are more.
Disadvantages:
1) Each time you call Select, you need to copy the Fd_set from the user space to the memory space to compare the consumption performance.
2) Wait, you need to traverse all the FD, the consumption ratio is large.
3) Select supported file size, the default is only 1024, if need to increase, you have to modify the macro fd_setsize value, and compile the kernel (trouble, and Fd_set in the number of files, the cost of each traversal is very large).
2. Pool
The implementation of poll is very similar to select, except that it describes the FD collection in different ways, poll uses the POLLFD structure rather than the fd_set structure of the Select, and the others are the same.
3. Epool
Epool is an improved version of Select and poll,
* First Use int epoll_create (int size) to create an event space in memory that specifies size.
* Then use int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event), Event registration function, register new FD to EPFD Epool object space, and indicate event (readable and writable), Note: In the process of registering the new event FD, the callback function of FD corresponding to the kernel interrupt handler is also callback, telling the kernel that once the FD is interrupted, it is put into the ready queue.
* Then use int epoll_wait (int epfd, struct epoll_event * events, int maxevents, int timeout), take FD in the ready queue corresponding to Epool object, and use memory map m Map copy to User space.
* then process the associated FD in the user space in turn.
Advantages:
1) Support a process to open a large number of socket descriptors
Select a process open FD is limited, set by Fd_setsize, the default value is 1024. Epool can open the number of FD can be very large, generally 1GB of memory has more than 100,000 FD number, the specific number can be Cat/proc/sys/fs/file-max view.
2) IO efficiency does not decrease linearly with the increase of FD number
3) Use MMAP to accelerate message delivery between the kernel and user space
use of Epool:
Epoll related system calls
Epoll only epoll_create,epoll_ctl,epoll_wait 3 system calls.
1. int epoll_create (int size);
Creates a handle to a epoll. Since linux2.6.8, the size parameter has been ignored. It should be noted that when the Epoll handle is created, it will occupy an FD value, under Linux if the view/proc/process id/fd/, is able to see the FD, so after the use of Epoll, you must call Close (), or it may cause FD to be exhausted.
2. int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);
The event registration function of Epoll, unlike select (), is to tell the kernel what type of event to listen to when it listens to events, but to register the type of event to listen on first.
The first parameter is the return value of Epoll_create ().
The second parameter represents an action, represented by three macros:
Epoll_ctl_add: Register the new FD to EPFD;
Epoll_ctl_mod: Modify the monitoring events of the registered FD;
Epoll_ctl_del: Delete a fd from the EPFD;
The third parameter is the FD that needs to be monitored.
The fourth parameter is to tell the kernel what to listen for, struct epoll_event structure as follows:
Save data related to a file descriptor that triggered the event (related to how it was used)
typedef Union EPOLL_DATA {
void *ptr;
int FD;
__uint32_t u32;
__uint64_t U64;
} epoll_data_t;
Events of interest and events that are triggered
struct Epoll_event {
__uint32_t events; /* Epoll Events */
epoll_data_t data; /* USER Data variable */
};
Events can be a collection of several macros:
Epollin: Indicates that the corresponding file descriptor can be read (including a graceful shutdown of the peer socket);
Epollout: Indicates that the corresponding file descriptor can be written;
Epollpri: Indicates that the corresponding file descriptor has an urgent data readable (this should indicate the arrival of out-of-band data);
Epollerr: Indicates an error occurred in the corresponding file descriptor;
Epollhup: Indicates that the corresponding file descriptor is hung up;
Epollet: Set Epoll to edge triggered mode, which is relative to the horizontal trigger (level triggered).
Epolloneshot: Listen to only one event, when the event is monitored, if you still need to continue to listen to the socket, you need to add the socket to the Epoll queue again
3. int epoll_wait (int epfd, struct epoll_event * events, int maxevents, int timeout);
Collects events that have been sent in epoll monitored events. The parameter events is an array of allocated epoll_event structures, and Epoll will assign the event to the events array (events cannot be null pointers, the kernel is only responsible for copying the data into the events array, not helping us to allocate memory in the user state). Maxevents the kernel of this events how large, the value of this maxevents can not be greater than the size of the creation of Epoll_create (), the parameter timeout is the time-out (milliseconds, 0 will immediately return, 1 will be uncertain, there is also said to be permanently blocked). If the function call succeeds, returns the number of file descriptors that have been prepared on the I/O, such as returning 0 to indicate a timeout.
Use Cases
Wrote a class that encapsulates the interface used by Epool:
#include <sys/epoll.h>class fdevent{int evfd;struct epoll_event *events;int maxfds;bool nonblocking;int epet; public:typedef int eventtype; fdevent (int max_client_num, bool is_nonblocking): Maxfds (Max_client_num), nonblocking (is_nonblocking) {if (evfd = Epoll_create (Maxfds)) = =-1) {perror ("epoll_create error!"); Exit (1);} if (Fcntl (evfd, f_setfd, fd_cloexec) = =-1) {perror ("epoll_create error!"); Exit (1);} Events = new Epoll_event[max_client_num];epet = 0;//nonblocking? epollet:0;} ~fdevent () {delete[] events;} int wait (int timeout) {return epoll_wait (evfd, events, Maxfds, timeout);} int add (int fd, BOOL init = false) {epoll_event ev;if (init) {ev.events = Epollin;} else{ev.events = Epollin|epet;} Ev.data.u64 = 0;EV.DATA.FD = Fd;if (Epoll_ctl (evfd, Epoll_ctl_add, FD, &ev) = =-1) {perror ("Epoll_add error!"); return-1;} return 0;} int del (int fd) {epoll_event ev;ev.data.fd = fd;if (Epoll_ctl (evfd, Epoll_ctl_del, FD, &ev) = =-1) {perror ("Epoll_del er Ror! "); return-1;} return 0;} Pair<int, EventtypE> get (uint32_t i) {return Make_pair (EVENTS[I].DATA.FD, events[i].events);} BOOL Iseventin (EventType t) {return t&epollin;}}; Used: int n = fde.wait ( -1), for (int i=0; i<n; i++) {pair<int, fdevent::eventtype> p = fde.get (i); if (P.first = = listenfd) {int clientfd = accept (LISTENFD, (struct sockaddr *) &remote_addr, & ; adsize); Fde.add (CLIENTFD); } else if (Fde.iseventin (P.second)) {Fde.del (P.first); }}
Reference article:
1. http://blog.csdn.net/xiajun07061225/article/details/9250579# (The speaking epool of this comparative system)
2. http://watter1985.iteye.com/blog/1614039 (This is the Select, pool and Epool source analysis)
3. http://www.cnblogs.com/Anker/p/3265058.html (This is a good summary)
IO multiplexing technology for Linux: The difference between select, pool, Epool and the principle and use of epool