struct epoll_event {_u32 events;union {void * ptr;int fd;_u32 u32;_u64 u64;}data;};
Epoll_ctl () is associated with the epoll instance and epfd. The OP parameter specifies the operation to be performed on FD. The event parameter describes more specific epoll behaviors.
The following are the valid values of the OP parameter:
Epoll_ctl_addAdd the file specified by FD to the epoll instance listening set specified by epfd to listen for events defined in the event.
Epoll_ctl_delDelete the file specified by FD from the epoll listener set specified by epfd.
Epoll_ctl_modUse event to change the listening behavior on the existing FD.
The event parameter in the epoll_event struct lists the events monitored on the given file descriptor. Multiple events can be specified simultaneously using bitwise OR operations. The following are valid values:
EpollerrFile error. Even if this flag is not set, this event is also monitored.
EpolletEdge trigger. The default value is horizontal triggering.
EpollhupThe file is suspended. Even if this flag is not set, this event is also monitored.
EpollinThe file is not blocked and readable.
EpolloneshotAfter an event is generated and processed, the file is not monitored. It must not be listened on again. You must use epoll_ctl_mod to specify a new event to re-Listen to the file.
EpolloutThe file is not blocked and can be written.
EpollpriHigh-priority out-of-band data is readable.
The data field in event_poll is used by the user. After the listener event is confirmed, data is returned to the user. Generally, the event. Data. FD is set to fd, so that you can know the file descriptor trigger event.
When the call succeeds, epoll_ctl () returns 0. If the call fails,-1 is returned, and errno is set to the following values:
EbadfEpfd is not a valid epoll instance, or FD is not a valid file descriptor.
EexistOP is epoll_ctl_add, but FD is already associated with epfd.
EinvalEpfd is not an epoll instance. epfd is the same as FD, or op is invalid.
EnoentOP is epoll_ctl_mod or epoll_ctl_del, but FD is not associated with epfd.
EnomenThere is not enough memory to complete the process request.
EpermFD does not support epoll.
Add a listener file specified by FD to the epfd instance and use the following code:
struct epoll_event event;int ret;event.data.fd = fd;/*return the fd to us later*/event.events = EPOLLIN|EPOLLOUT ;ret = epoll_ctl (epfd,EPOLL_CTL_MOD,fd,&event);if (ret)perror ("epoll_ctl");
You can use the following code to modify a listener event on the FD of an epfd instance:
struct epoll_event event;int ret;event.data.fd = fd;/*return the fd to us later*/event.events = EPOLLIN ;ret = epoll_ctl (epfd,EPOLL_CTL_MOD,fd,&event);if (ret)perror ("epoll_ctl");
To delete an FD listening event, use the following code:
struct epoll_event event;int ret;event.data.fd = fd;/*return the fd to us later*/event.events = EPOLLIN ;ret = epoll_ctl (epfd,EPOLL_CTL_DEL,fd,&event);if (ret)perror ("epoll_ctl");
3. Wait for the epoll event
Epoll_wait:
#include <sys/epoll.h>int epoll_wait (int epfd, struct epoll_event * * events, int maxevents, int timeout);
Call epoll_wait () to wait for the event on the file FD in the epfd of the epoll instance. The time limit is timeout milliseconds. If a success is returned, events points to the memory containing the epoll_event struct (which describes each event,
You can have a maximum of maxevents events. The returned value is the number of events, error-1 is returned, and errno is set to the following values
EbadfEpfd is an invalid file descriptor.
EfaultThe process has no write permission on the memory indicated by events.
EintrSystem Call is interrupted by signal before completion
EinvalEpfd is not a valid epoll instance, or maxevents is less than or equal to 0
If the timeout value is 0, the call will occur immediately even if no event occurs. At this time, the call will return 0. If the timeout value is-1, the call will wait until an event occurs.
When epoll_wait () is called to return, the events array in the epoll_event struct describes a waiting event, and a maximum of maxevents events are returned. The data field contains the user's settings before calling epoll_ctl,
For example, the file handle is used to differentiate the events that occur in the file.
An example of a complete epoll_wait () is as follows:
#define MAX_EVENTS 64struct epoll_event * events = NULL;int nr_events, i, epfd;events = malloc (sizeof(struct epoll_event) * MAX_EVENTS);if (! events ){perror("malloc");exit(-1);}nr_events = epoll_wait (epfd,events,MAX_EVENTS,-1);if (nr_events < 0){perror("epoll_wait");free(events);exit (-1);}for (int i=0; i<nr_eventsl i++)printf("event = %d on fd = %d \n",events[i].events,events[i].data.fd);
4. Edge trigger time and horizontal trigger event
There are two types of epoll events:Level triggered (LT)AndEdge triggered (ET ):
LT (Level triggered, horizontal trigger mode) is the default mode of work, and supports both block and non-block socket. In this way, the kernel tells you whether a file descriptor is ready, and then you can perform Io operations on this ready FD. If you do not perform any operation, the kernel will continue to inform you, so the possibility of programming errors in this mode is lower.
Et (edge-triggered, edge trigger mode) is a high-speed operation mode that only supports no-block socket. In this mode, when the descriptor is never ready, the kernel tells you through epoll. Then it will assume that you know that the file descriptor is ready and will not send more ready notifications for that file descriptor. The event will not be ready again until new data comes in next time.
5. Instances in man epoll
The setnonblocking () function sets the socket file to non-blocking because the et mode is used. Do_use_fd () is used to process this file, such as reading and writing.
#define MAX_EVENTS 10struct epoll_event ev, events[MAX_EVENTS];int listen_sock, conn_sock, nfds, epollfd;/* Set up listening socket, ‘listen_sock‘ (socket(), bind(), listen()) */epollfd = epoll_create(10);if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE);}ev.events = EPOLLIN;ev.data.fd = listen_sock;if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE);}for (;;) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listen_sock) { conn_sock = accept(listen_sock, (struct sockaddr *) &local, &addrlen); if (conn_sock == -1) { perror("accept"); exit(EXIT_FAILURE); } setnonblocking(conn_sock); ev.events = EPOLLIN | EPOLLET; ev.data.fd = conn_sock; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else { do_use_fd(events[n].data.fd); } }}