Epoll use detailed explanation

  
 

The working principle of epoll is that if you want to perform IO operations, first ask epoll whether it is readable or writable. If it is in a readable or writable state, epoll will notify you via epoll_wait function. Perform further recv or send operations.

epoll is just a notification mechanism for asynchronous events. It does not do any IO read and write operations. It is only responsible for telling you whether it can be read or written, but the specific read and write operations. The application layer works by itself. It is also very good that epoll only provides this mechanism. It maintains the independence between event notification and IO operations, making epoll more flexible.

All functions used by epoll are declared in the header file sys/epoll.h. The following is a brief description of the data structures and functions used:

The data structure typedef union used. Epoll_data {void *ptr;int fd;__uint32_t u32;__uint64_t u64;} epoll_data_t;

struct epoll_event {__uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */}; Epoll_event is used to register events of interest and pending events that occur,

epoll_data is used to store data related to a file descriptor that triggers an event, such as a client connecting to the server. The server can obtain the socket file descriptor corresponding to the client by calling the accept function, and can assign the file descriptor to the fd field of the epoll_data so that the subsequent read and write operations are performed on the file descriptor

a, *ptr: Carry the application layer data through the pointer ptr. When the notification of the event comes, it not only tells you what kind of event happened, but also tells the data of the event operation

epoll_event The events field of the structure is the value of the event indicating the event of interest and the event that is triggered:

EPOLLIN: indicates that the corresponding file descriptor can be read; EPOLLOUT: indicates that the corresponding file descriptor can be written; EPOLLPRI: indicates that the corresponding file descriptor has urgent data readable (here should indicate that there is out-of-band data coming); EPOLLERR: indicates that the corresponding file descriptor has an error; EPOLLHUP: indicates that the corresponding file descriptor is hanged; EPOLLET: Indicates that the corresponding file descriptor has an event;

functions used: 1, epoll_create function declaration: int epoll_create(int size) This function generates an epoll-specific file descriptor, where the parameters are specified. The maximum range of generated descriptors

2, epoll_ctl function declaration: int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) This function is used to control events on a file descriptor, You can register events, modify events, and delete events. Parameters: epfd: epoll-specific file descriptor generated by epoll_create; op: operations to be performed such as registration events, possible values ​​EPOLL_CTL_ADD registration, EPOLL_CTL_MOD modification, EPOLL_CTL_DEL deletion fd: associated file descriptor; event: pointing to epoll_event Pointer; if the call returns 0, the unsuccessful return -13, epoll_wait function

Function declaration: int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout) This function is used to poll I/O event occurrence; parameters: epfd: epoll-specific file descriptor generated by epoll_create; epoll_event: array for returning generation events; maxevents: number of events that can be processed each time; timeout: waiting for I/O events to occur Timeout value; returns the number of events that occurred.



In linux network programming, select is used for event triggering for a long time. In the new kernel of linux, there is a mechanism to replace it, which is epoll. Compared to select, the biggest benefit of epoll is that it does not reduce efficiency as the number of listening fds grows. Because in the select implementation in the kernel, it is handled by polling, the more the number of fd polled, the more time it takes. Also, the linux/posix_types.h header file has such a declaration: #define __FD_SETSIZE 1024 means that select can listen to 1024 fd at the same time. Of course, you can expand the number by modifying the header file and recompiling the kernel, but this does not seem to be a cure. .

The interface of epoll is very simple. There are three functions: 1. int epoll_create(int size); Create an epoll handle, size is used to tell the kernel how many monitors there are. This parameter is different from the first parameter in select() and gives the value of fd+1 for the largest listener. It should be noted that when the epoll handle is created, it will occupy an fd value. If you view /proc/process id/fd/under linux, you can see this fd, so after using epoll, you must Call close() to close, otherwise it may cause fd to be exhausted.

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epoll event registration function, it is different from select() which tells the kernel what type to listen to when listening for events Event, but here to register the type of event to be listened to. The first parameter is the return value of epoll_create(), the second parameter represents the action, which is represented by three macros: EPOLL_CTL_ADD: register new fd to epfd; EPOLL_CTL_MOD: modify the listening event of registered fd; EPOLL_CTL_DEL: from Epfd deletes an fd; the third parameter is the fd to be listened to, the fourth parameter tells the kernel what to monitor, the struct epoll_event structure is as follows:

typedef union epoll_data {void *ptr;int fd; __uint32_t u32;__uint64_t u64;} epoll_data_t;

struct epoll_event {__uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */};

events can be the following A collection of macros: EPOLLIN: indicates that the corresponding file descriptor can be read (including the peer SOCKET is normally closed); EPOLLOUT: indicates that the corresponding file descriptor can be written; EPOLLPRI: indicates that the corresponding file descriptor has urgent data to read ( This should indicate that there is an out-of-band data arrival; EPOLLERR: indicates that the corresponding file descriptor has an error; EPOLLHUP: indicates that the corresponding file descriptor is hanged; EPOLLET: EPOLL is set to Edge Triggered mode, which is relative to Level Triggered. EPOLLONESHOT: Only listen for one event. After listening to this event, if you need to continue listening to this socket, you need to add this socket to the EPOLL queue again.

3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); wait for events to be generated, similar to the select() call. The parameters events are used to get the collection of events from the kernel. maxevents tells the kernel how big the events are. The maxevents value cannot be larger than the size when creating epoll_create(). The timeout is the timeout (milliseconds, 0 will return immediately, -1 will Uncertain, there are also statements that are permanently blocked). This function returns the number of events that need to be processed, such as returning 0 to indicate that it has timed out.

Copyright © Windows knowledge All Rights Reserved