#include <sys/epoll.h>
int epoll_create(int size);
int epoll_create1(int flags);
--When you program on linux kernel version higher than 2.6.8, you should ignore the parameter "size", you should give the paramater bigger than 0 sitll. The parameter is the file descriptor and can do dynamically allocation. So you should just give a bigger than 0 parameter to be compatible for lower version of linux kernel.
--in epoll_create1(), if the "flags" is 0, it is equal to epoll_create() except for the obsolete size abandonment. "flags" can be EPOLL_CLOEXEC, check O_CLOEXEC to understand EPOLL_CLOEXEC.
--return values: Nonnegative number (actually it's fd) for success, -1 for failure and please check error codes.
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
--There is 3 kinds of op values:
1) EPOLL_CTL_ADD means register fd(file descriptor) into epfd and associate event with fd.
2) EPOLL_CTL_MOD means modify the relationship between fd and event.
3) EPOLL_CTL_DEL means the deletion of fd in epfd, event can be ignored and it can be NULL.
--As for struct epoll_event:
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 */
};
--The paramater events has forwads events:
EPOLLIN: while the fd it assciates can do read() operates
EPOLLOUT: write() operates
EPOLLRDHUP: (since linux 2.6.17)when socket close, or half close write part(when you use Edge-Triggered, this identification is good for test codes to check closing).
EPOLLPRI: when read() can do urgent data
EPOLLERR: while the file which it associate has something wrong, epoll_wait() will always wait this event, it is not a identification which must be set
EPOLLHUP: means hang up. epoll_wait() will always wait for this event, it is not a identification which must be set. When socket read data from somewhere(pipping or socket), this event is just identifying this is the end of reading(EOF). Any valid data is compeletely read, after that, it will return 0 for any read operation (EOF).
EPOLLET: set the file descriptor to Edge-Trigger, the default is Level-Triggered
EPOLLONESHOT: (since linux 2.6.17) set file descriptor to once mode. It means, it will be one time for epoll_wait() to catch the event, after that you must call epoll_ctl() again to set it again.
return values: 0 for success, -1 for failuer and errno:
EBADF - epfd or fd is invalid
EEXIST - op is EPOLL_CTL_ADD, but the fd you want to register is already registered
EINVAL - epdf is not a epoll descriptor, or epfd is equal to fd, or op parameter illegal
ENOENT - op is POLL_CTL_MOD or POLL_CTL_DEL, but fd hasn't been registered into epoll.
ENOMEM - not enuf cache
EPERM - the objective fd doesn't support epoll
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int pepoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);
--epoll_wait()is called for waiting for events in epfd, events point to stack area of events which caller can use. maxevents tell kernel the number of events and must larger than 0. time out is to formulate the blocking time(millisecond) of epoll_wait() and block until forward conditions:
1) a fd trigger a event
2) is interrupt by a signal handle function or timeout
if(timeout == -1) forever waiting(block)
if(timeout == 0) return even if no events
--As for epoll_pwait()
ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);
at interior it is equal to:
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = epoll_wait(epfd, &events, maxevents, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
--Thus if &sigmask is NULL, it is equal to epoll_wait()
return values:
>0: numbers of ready IO events
=0: timeout
-1: failure and please check the error code:
EBADF - epfd is a invalid fd
EFAULT - no access authority of cache which pointer events point to
EINRE - this calling is interrupted by signal.
EINVAL - epfd is not an epoll descriptor, or maxevents <= 0
------OFFICIAL DEMO------
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Code to set up listening socket, 'listen_sock', * (socket(), bind(), listen()) omitted */
epollfd = epoll_create1( 0 );
if ( epollfd == -1 ) {
perror( "epoll_create1" );
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_wait" );
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 );
}
}
}