问题
I have gone through a variaty of different linux named pipe client/server implementations but most of them use the blocking defaults on reads/writes.
As I am already using poll() to check other flags I though it would be a good idea to check for incoming FIFO data via poll() as well...
After all the research I think that opening the pipe in O_RDWR mode is the only way to prevent an indefinitely number of EOF events on a pipe when no writer has opened it.
This way both ends of the pipe are closed and other clients can open the writable end as well. To respond back I would use separate pipes...
My problem is that although I have found some examples that use the O_RDWR flag the open() manpages describe this flag as being unefined when assigned to a FIFO. (http://linux.die.net/man/3/open)
But how would you use poll() on a pipe without O_RDWR? Do you think "O_RDWR" is a legitimate way to open pipes???
回答1:
First, some preliminaries:
Using O_NONBLOCK
and poll()
is common practice -- not the other way around. To work successfully, you need to be sure to handle all poll()
and read()
return states correctly:
read()
return value of0
means EOF -- the other side has closed its connection. This corresponds (usually, but not on all OSes) topoll()
returning aPOLLHUP
revent. You may want to check forPOLLHUP
before attemptingread()
, but it is not absolutely necessary sinceread()
is guaranteed to return0
after the writing side has closed.- If you call
read()
before a writer has connected, and you haveO_RDONLY | O_NONBLOCK
, you will get EOF (read()
returning0
) repeatedly, as you've noticed. However, if you usepoll()
to wait for aPOLLIN
event before callingread()
, it will wait for the writer to connect, and not produce the EOFs. read()
return value-1
usually means error. However, iferrno == EAGAIN
, this simply means there is no more data available right now and you're not blocking, so you can go back topoll()
in case other devices need handling. Iferrno == EINTR
, thenread()
was interrupted before reading any data, and you can either go back topoll()
or simply callread()
again immediately.
Now, for Linux:
- If you open on the reading side with
O_RDONLY
, then:- The
open()
will block until there is a corresponding writer open. poll()
will give aPOLLIN
revent when data is ready to be read, or EOF occurs.read()
will block until either the requested number of bytes is read, the connection is closed (returns 0), it is interrupted by a signal, or some fatal IO error occurs. This blocking sort of defeats the purpose of usingpoll()
, which is whypoll()
almost always is used withO_NONBLOCK
. You could use analarm()
to wake up out ofread()
after a timeout, but that's overly complicated.- If the writer closes, then the reader will receive a
poll()
POLLHUP
revent andread()
will return0
indefinitely afterwards. At this point, the reader must close its filehandle and reopen it.
- The
- If you open on the reading side with
O_RDONLY | O_NONBLOCK
, then:- The
open()
will not block. poll()
will give aPOLLIN
revent when data is ready to be read, or EOF occurs.poll()
will also block until a writer is available, if none is present.- After all currently available data is read,
read()
will either return -1 and seterrno == EAGAIN
if the connection is still open, or it will return0
if the connection is closed (EOF) or not yet opened by a writer. Whenerrno == EAGAIN
, this means it's time to return topoll()
, since the connection is open but there is no more data. Whenerrno == EINTR
,read()
has read no bytes yet and was interrupted by a signal, so it can be restarted. - If the writer closes, then the reader will receive a
poll()
POLLHUP
revent, andread()
will return0
indefinitely afterwards. At this point the reader must close its filehandle and reopen it.
- The
- (Linux-specific:) If you open on the reading side with
O_RDWR
, then:- The
open()
will not block. poll()
will give aPOLLIN
revent when data is ready to be read. However, for named pipes, EOF will not causePOLLIN
orPOLLHUP
revents.read()
will block until the requested number of bytes is read, it is interrupted by a signal, or some other fatal IO error occurs. For named pipes, it will not returnerrno == EAGAIN
, nor will it even return0
on EOF. It will just sit there until the exact number of bytes requested is read, or until it receives a signal (in which case it will return the number of bytes read so far, or return -1 and seterrno == EINTR
if no bytes were read so far).- If the writer closes, the reader will not lose the ability to read the named pipe later if another writer opens the named pipe, but the reader will not receive any notification either.
- The
- (Linux-specific:) If you open on the reading side with
O_RDWR | O_NONBLOCK
, then:- The
open()
will not block. poll()
will give aPOLLIN
revent when data is ready to be read. However, EOF will not causePOLLIN
orPOLLHUP
revents on named pipes.- After all currently available data is read,
read()
will return-1
and seterrno == EAGAIN
. This is the time to return topoll()
to wait for more data, possibly from other streams. - If the writer closes, the reader will not lose the ability to read the named pipe later if another writer opens the named pipe. The connection is persistent.
- The
As you are rightly concerned, using O_RDWR
with pipes is not standard, POSIX or elsewhere.
However, since this question seems to come up often, the best way on Linux to make "resilient named pipes" which stay alive even when one side closes, and which don't cause POLLHUP
revents or return 0
for read()
, is to use O_RDWR | O_NONBLOCK
.
I see three main ways of handling named pipes on Linux:
(Portable.) Without
poll()
, and with a single pipe:open(pipe, O_RDONLY);
- Main loop:
read()
as much data as needed, possibly looping onread()
calls.- If
read() == -1
anderrno == EINTR
,read()
all over again. - If
read() == 0
, the connection is closed, and all data has been received.
- If
(Portable.) With
poll()
, and with the expectation that pipes, even named ones, are only opened once, and that once they are closed, must be reopened by both reader and writer, setting up a new pipeline:open(pipe, O_RDONLY | O_NONBLOCK);
- Main loop:
poll()
forPOLLIN
events, possibly on multiple pipes at once. (Note: This preventsread()
from getting multiple EOFs before a writer has connected.)read()
as much data as needed, possibly looping onread()
calls.- If
read() == -1
anderrno == EAGAIN
, go back topoll()
step. - If
read() == -1
anderrno == EINTR
,read()
all over again. - If
read() == 0
, the connection is closed, and you must terminate, or close and reopen the pipe.
- If
(Non-portable, Linux-specific.) With
poll()
, and with the expectation that named pipes never terminate, and may be connected and disconnected multiple times:open(pipe, O_RDWR | O_NONBLOCK);
- Main loop:
poll()
forPOLLIN
events, possibly on multiple pipes at once.read()
as much data as needed, possibly looping onread()
calls.- If
read() == -1
anderrno == EAGAIN
, go back topoll()
step. - If
read() == -1
anderrno == EINTR
,read()
all over again. - If
read() == 0
, something is wrong -- it shouldn't happen withO_RDWR
on named pipes, but only withO_RDONLY
or unnamed pipes; it indicates a closed pipe which must be closed and re-opened. If you mix named and unnamed pipes in the samepoll()
event-handling loop, this case may still need to be handled.
- If
回答2:
According to open(2) man page, you can pass O_RDONLY|O_NONBLOCK
or O_WRONLY|O_NONBLOCK
to avoid the open
syscall to be blocked (you'll get errno == ENXIO
in that case)
As I commented read also the fifo(7) and mkfifo(3) man pages.
来源:https://stackoverflow.com/questions/15055065/o-rdwr-on-named-pipes-with-poll