views:

836

answers:

6

When sockets are created or files are opened/created in C, is the file descriptor that's assigned to the socket/file guaranteed to be the lowest-valued descriptor available? What does the C spec say about file descriptor assignment in this regard, if anything?

+2  A: 

I don't think you'll find it in the C spec, more likely the spec for your OS. My experience in Linux has been that it's always the lowest.

Steve M
+2  A: 

I'll counter this with another question - why does this matter? You shouldn't be comparing the file descriptor with anything (unless checking for stdin/stdout/stderr) or doing math with it. As long as it fits in an int (and its guaranteed to) that's all you really need to know.

Kyle Cronin
Not true. Using it with select requires it to fit into an `fd_set` object. And since POSIX requires file descriptors to be allocated sequentially, you might similarly want to use your own bit-array objects for storing sets of file descriptors, which you can do portably.
R..
A: 

Steve M is right; C has no notion of sockets, and its file I/O functions use a [pointer to a] FILE object, not a descriptor.

aib
C actually has two ways of reading files, one with the FILE object and one with the file descriptor.
Kyle Cronin
The file descriptor based way is the system call interface provided by the Unix API, not part of C proper.
wnoise
+3  A: 

It's not guaranteed to be the lowest, and is implementation dependent (1). In general, however, the routine that assigns open file descriptors uses a method that gives you the first open on. It could be that immediately after several lower ones free, leaving you with a higher descriptor than you might expect though.

The only reason I can think of to know this, though, is for the select function, which is sped up if you pass it the highest file descriptor you need to check for.

(1) Note that those implementations that follow the IEEE standard do guarantee the lowest unused descriptor for files, but this may not apply to sockets. Not every implementation follows the IEEE standard for open(), so if you're writing portable software it is best not to depend on it.

Adam Davis
Calling open() is guaranteed to return the lowest available file descriptor: http://www.opengroup.org/onlinepubs/009695399/functions/open.htmlThere appears to be no such guarantee for sockets.
Ville Laurikari
Thanks for the reminder and specific reference!
Adam Davis
"The IEEE standard" being referred to is POSIX. It would be worthwhile to mention this...
R..
A: 

@aib the open(), close(), lseek(), read(), write() all make use of file descriptors. I hardly ever use streams for I/O.

@Kyle it matters because of statements like select(). Knowing the highest descriptor can improve performance.

A: 

The C spec says that it's implementation dependent. If you're looking at a Unix implementation, the man page for open(2) says "The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process."

This helps if you're trying to attach a specific file to a specific descriptor. Say you want to redirect stderr to /dev/null. Something like

close(2); open("/dev/null", O_WRONLY);

ought to do it. You should, of course, capture the fd returned by open and ensure that it's 2.

mpez0
Or, use `dup2` to ensure you assign the correct stream to the intended file descriptor.
LnxPrgr3
If your program uses threads and you don't have tight control over what the other threads are doing, `dup2` is the only safe way. `close`/`open` introduces a race condition, during which another thread may get the file descriptor.
R..