How does a socket event get propagated/converted to epoll?

c, centos6, glibc, linux, linux-kernel

Solution

The most glaring problem with `epoll` documentation is its failure to state in "bold caps" that `epoll` events, are, in fact, fully identical to `poll` (2) events. Indeed, on the kernel side `epoll` handles its events in terms of older `poll` event names:

#define POLLIN     0x0001  // EPOLLIN
#define POLLPRI    0x0002  // EPOLLPRI
#define POLLOUT    0x0004  // EPOLLOUT
#define POLLERR    0x0008  // EPOLLERR
#define POLLHUP    0x0010  // EPOLLHUP
#define POLLNVAL   0x0020  // unused in epoll
#define POLLRDNORM 0x0040  // EPOLLRDNORM
#define POLLRDBAND 0x0080  // EPOLLRDBAND
#define POLLWRNORM 0x0100  // EPOLLWRNORM
#define POLLWRBAND 0x0200  // EPOLLWRBAND
#define POLLMSG    0x0400  // EPOLLMSG
#define POLLREMOVE 0x1000  // unused in epoll
#define POLLRDHUP  0x2000  // EPOLLRDHUP

Then, a brief inspection of kernel source reveals that:

`EPOLLIN` and `EPOLLRDNORM` are identical (epoll returns `EPOLLIN | EPOLLRDNORM` when data is available for reading from the file descriptor).

`EPOLLOUT` and `EPOLLWRNORM` are identical (epoll returns `EPOLLOUT | EPOLLWRNORM` when buffer space is available for writing).

`EPOLLRDBAND` and `EPOLLWRBAND` signal availability of the out of band data on the descriptor (on some sockets this will be the data send with `MSG_OOB` flag passed to socket).

`EPOLLPRI` is a modifier flag and always augments some other event (such as `EPOLLERR`). It's use is subsystem dependent, as it may mean somewhat different things depending on what purpose associated file descriptor serves.

`EPOLLMSG` appears to be unused by the kernel and appears to serve no purpose.

`EPOLLRDHUP` signals that the peer had closed its side of the channel for reading, but may still receive data (handy to establish that no more request data is coming in).

`EPOLLHUP` signals that the peer had closed its side of the channel.

Problem

I am curious how epoll_wait() receives the event that a registered socket (with epoll_ctl()) is ready for read/write. I believe that glibc magically handles it. Then, is there a document describing how the following events can be triggered for a socket? - EPOLLPRI - EPOLLRDNORM - EPOLLRDBAND - EPOLLWRNORM - EPOLLWRBAND - EPOLLMSG - EPOLLERR - EPOLLHUP - EPOLLRDHUP P.S. Originally I was trying to paste the enum EPOLL_EVENTS in sys/epoll.h on my box here; stackoverflow thinks that I don't format the code block correctly although I wrapped it with pre and then code tag, any idea?

Original source

Related problems