Requesting help on intricacies of duplicated file descriptors.

Rich Felker dalias at aerifal.cx
Mon Jul 24 07:15:26 UTC 2006


On Sun, Jul 23, 2006 at 06:50:39PM +0000, Garrett Kajmowicz wrote:
> On Sunday 23 July 2006 03:35, Rich Felker wrote:
> 
> <snip>
> 
> > Also it's a bad idea to use non-blocking io with stdio streams (FILE
> > *) unless you really know what you're doing. If no input is available,
> > the read operation will return with error and set the error flag for
> > the stream. It can be cleared with fclearerr() and presumably you can
> > continue reading then, but nonblocking io is really the most useful in
> > connection with the non-buffering unix-style fd io functions.
> 
> Thanks for the primer.  The case I need to address is reading a minimum of one 
> character from a stream (blocking until the character is available or 
> returning error if we are EOF).  At the same time, I want to read as many 
> characters as possible (up to a limit) to go into some buffering code.  Yes, 
> stdio does buffering, however I need to do my own limited buffering for 
> uClibc++.  The current implementation switches between blocking and 
> non-blocking when doing reads, but I take it that this isn't a good idea.  
> 
> Instead, what is my best approach to read a minimum of 1 byte from the stream, 
> blocking only if needed to get that first byte?

There are two viable approaches:

1. Use the low level fd functions (like read(2)) instead of stdio
   streams. The read function will always return immediately if there
   is any data at all to be read, possibly reading less than the
   requested amount. (This is for special file descriptors like
   sockets, fifos, terminals (with the right tty modes), etc.;
   ordinary files are _always_ blocking in the sense that read might
   sleep while the kernel pages the data from disk.)

2. Just use getc and let stdio do all the buffering. :) getc should
   never block unless there are no characters available for reading.
   However this might not work for you if there's a reason you need to
   know _how much_ input is pending..

IMO if you're doing your own buffering you should take approach 1.
It's useless bloat having two layers of buffering and in fact it will
hurt performance and use more memory.. But if the calling application
needs to be able to switch back and forth between using your code and
using stdio on the same file (especially stdin), then you must use
stdio and you must not do any additional buffering. Otherwise the two
views of the file would become desynchronized.

Rich






More information about the uClibc mailing list