Question About Epoll and Splice

Question about epoll and splice

1st question

  1. You can use edge triggered rather then even triggered polling thus you do not have to delete socket each time.
  2. You can use EPOLLONESHOT to prevent removing socket

File descriptor has to become readable first and there will be some interval before socket will become writable.

What kind of file descriptor? If this file on file system you can't use select/poll or other tools for this purpose, file will be always readable or writeable regardless the state if disk and cache. If you need to do staff asynchronous you may use aio_* API but generally just read from file write to file and assume it is non-blocking.

If it is TCP socket then it would be writeable most of the time. It is better to use
non-blocking calls and put sockets to epoll when you get EWOULDBLOCK.

Distinguishing file descriptor types in epoll

Yes you have to compare the file descriptors. The example in the manual page does this.

chaining multiple epoll instances

From man epoll

Q3 Is the epoll file descriptor itself poll/epoll/selectable?

A3 Yes. If an epoll file descriptor has events waiting, then it will indicate as being readable.

How does epoll return the correct file descriptor

  1. So how does events[i].data.fd contain the socket file descriptor?

It's put in there by epoll_wait(). It fills in the events array with information about all the events that occurred.


  1. Why do we set ev.data.fd=listenfd; if we have an array of epoll_event, which has a file descriptor data member?

ev is used to register events to wait for with epoll_ctl(), the events array contains the events that occurred.

When to rearm epoll with edge mode & oneshot?

Should I rearm before calling a non-blocking operation or after?

Technically, after, but it's not as simple as that.

Regardless of EPOLLONESHOT, once you receive an edge-triggered event signalling read-readiness of a given file descriptor, you must consider that FD to continue to be ready until a read() on it fails with errno set to EAGAIN (and therefore the file must be in non-blocking mode). Over the course of those reads, it may be the case that you read all remaining bytes with one read(), but then more arrive before the next. In that case, if the FD is still armed then a new event for it will be queued (or merged with another event for that FD, as appropriate). This is the case that could result in you receiving an event when in fact the FD is not any longer ready.

You should consider just accepting those "phantom" events. Since your file will be in non-blocking mode, they will not cause unwanted stalls, just a little extra work. And your code will be simpler. But if you do use EPOLLONESHOT to avoid receiving phantom events, then you must not re-arm the FD before you determine it to be unready (via a read failing with EAGAIN), else you defeat the purpose.

Thus, the full answer is after the FD is determined to be unready. That will take at least two read()s, and possibly more. If the file becomes ready after the last read and before the rearming then the rearming should cause an appropriate event to be queued.

Is it necessary to deregister a socket from epoll before closing it?

From the man page:

Q6 Will closing a file descriptor cause it to be removed from all epoll sets
automatically?

A6 Yes, but be aware of the following point. A file descriptor is a
reference to an open file description (see open(2)). Whenever a
descriptor is duplicated via dup(2), dup2(2), fcntl(2) F_DUPFD, or
fork(2), a new file descriptor referring to the same open file description
is created. An open file description continues to exist until all file
descriptors referring to it have been closed. A file descriptor is
removed from an epoll set only after all the file descriptors referring to
the underlying open file description have been closed (or before if the
descriptor is explicitly removed using epoll_ctl(2) EPOLL_CTL_DEL). This
means that even after a file descriptor that is part of an epoll set has
been closed, events may be reported for that file descriptor if other file
descriptors referring to the same underlying file description remain open.

epoll VS select

select is the standard Unix facility for doing asynchronous IO. Its programming interface is quirky, and its implementation in most Unixes is mediocre at best. It also imposes a limit on the maximum number of descriptors a process can watch, which is inconvenient in an application. Regarding efficiency, the performance of select usually degrades linearly with the number of descriptors.

epoll is a huge improvement over select in terms of programming interface and efficiency, but is only provided in Linux starting from version 2.6. Other Unixes have their specialised calls, too.

Why epoll_wait() doesn't react on dup2(writable_fd, non_writable_fd)?

The problem is that epoll cares about "open file descriptions", not about file descriptors. The answer is hidden in a few layers of man pages. First, epoll_wait:

Will closing a file descriptor cause it to be removed from all epoll
sets automatically
?

Yes, but be aware of the following point. A file
descriptor is a reference to an open file description (see
open(2))[...]

Back to your dup2 call:

dup2(writable_fd, non_writable_fd)

dup2 call atomically first closes non_writable_fd and then makes it point to the same file description as writable_fd. Consider 2 cases:

  1. You didn't do anything special so your dup2 ends up closing the open file description associated with non_writable_fd. In this case epoll simply removes it from the set and that's that

  2. You had beforehand dup'd non_writable_fd into something else. In this case dup2 simply severs the association between non_writable_fd and its OFD, which lives on, watched by epoll

In both situations your dup call doesn't achieve what you want: you need to explicitly call epoll_ctl again.

how to assign a context to a socket or an epoll event

The epoll_event structure that you pass to epoll_ctl(), and which is filled in by epoll_wait(), has a data_ptr field.



Related Topics



Leave a reply



Submit