POSIX specifies an fdopen function that creates a FILE
for a file descriptor. POSIX also specifies a fileno function that returns the file descriptor for a FILE
. Together, these two could be used to create a second FILE
accessing the same underlying file descriptor as an existing file:
FILE *secondfile(FILE *f, const char *mode)
{
int fd = fileno(f);
return fd >= 0 ? fdopen(fd, mode) : NULL;
}
Is this a well-defined operation under POSIX? What happens when I access both the original FILE
and the second FILE
I made for the same file descriptor? Is the interaction specified? If yes, how?
Historically, Unices used a fixed table of FILE
structures for the 20 files you could open. Calling fdopen()
on a file descriptor that has already been associated with a FILE
would thus corrupt the existing file and yield undefined behaviour. I am not sure if such an implementation of stdio
is still allowed by POSIX, which is why I am asking this question.
One process can have multiple file descriptors point to the same entry (e.g., as a result of a call to dup() ) Multiple processes (e.g., a parent and child) can have file descriptors that point to the same entry.
File descriptors are generally unique to each process, but they can be shared by child processes created with a fork subroutine or copied by the fcntl, dup, and dup2 subroutines.
Hard Limits The hard limit of a resource is the maximum value that a user can increase their soft limit to. Thus, we know that this system's hard limit for the number of open file descriptors is 4096.
Threads in the same process share an address space and file descriptor table, so we do not need to save the page-table root pointer or the fd table.
POSIX explicitly permits multiple "handles" to be associated simultaneously with the same underlying "open file description", where handles can be either file descriptors or streams. Although it does not specifically address multiple streams opened via fdopen()
on the same file descriptor, I see no reason to suppose that these would be subject to more or different requirements than any two streams associated with the same open file description are generally subject to.
POSIX defines constraints on how two handles on the same open file description may be used in order to avoid undefined behavior. It is relevant here that those constraints are few indeed for handles that are file descriptors; almost all of them apply to streams, and they are organized mainly around conditions related to buffering. The exceptions are related to positioning.
If you use your streams in a manner consistent with those constraints -- mostly, but not exclusively, by ensuring that output is not buffered unwritten in one stream when you switch to using the other -- you can expect the stream I/O functions to behave as documented. Otherwise, the behavior is explicitly undefined.
Given a typical Unix implementation, with a FILE data structure containing a file descriptor to read from, and a buffer for, eh, buffering, and if you know the size of the buffer, and the policy for filling it (when the data is needed, not immediately when the buffer is empty), I would say that you can determine what will happen. But I don't know what the POSIX standard says, and I do know that it will be a difficult thing to use in a program. ("Ok, so I've read the first 4096 bytes from the file on disk into this FILE, and the next 4096 bytes into that FILE, and the third 4096-byte chunk from the file will be read into the FILE that reaches the end of its buffer first and needs to read more...")
(I've never done anything like this deliberately, but I seem to remember such symptoms from debugging code that got FILEs and file descriptors mixed up.)
My guess would be that POSIX doesn't specify this well enough that it will be guaranteed to work. For example, does POSIX specify when a buffer inside a FILE will be filled by reading from the file descriptor? When empty, when empty and more data is needed, or either of these, depending on something? Depending on choice there, data from the file descriptor will show up in different FILEs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With