D. J. Bernstein
Asynchronous access to disk files
UNIX kernel designers should provide
an O_HONESTBLOCKING option to open()
that has the same blocking effects as
opening a pipe to a separate program that accesses the file.
Specifically, here are the effects on reading:
Similarly, here are the effects on writing:
- A memory buffer, just like a pipe from a separate program,
is allocated for reading the ofile.
- Whenever the buffer is empty, the kernel starts a disk read;
when the disk read finishes,
the kernel copies data from the disk cache into the buffer.
one page of data from the file is locked into memory;
the point is that the data will be immediately accessible
to a subsequent read().)
- select(), poll(), etc. do not show the descriptor as ready for reading
if there is no data in the buffer.
- A non-blocking read() returns EAGAIN
if there is no data in the buffer,
rather than blocking while data is read from disk.
For extra credit,
also add an O_OPENLATER option
meaning that open() always succeeds immediately
(if descriptor space is available),
with errors such as EACCES reported on the first read() or write().
- A memory buffer, just like a pipe to a separate program,
is allocated for writing the ofile.
- Whenever the buffer is full,
the kernel copies data from the buffer to the disk cache;
this may mean waiting for a disk cache block to be flushed.
- select(), poll(), etc. do not show the descriptor as ready for writing
if the buffer is full.
- A non-blocking write() returns EAGAIN
if the buffer is full,
rather than blocking while a disk cache block is flushed.
Similar effects to O_HONESTBLOCKING can be achieved on some kernels with
the aio_read() and aio_write() functions.
The difference is that O_HONESTBLOCKING
works with a traditional select()/poll() loop,
traditional non-blocking read(), etc.
Perhaps O_HONESTBLOCKING should be the default in UNIX.
Why would a program bother using select(), poll(), non-blocking read(), etc.
if it is unprepared for the possibility of descriptors not being ready?