問題描述
為同一個文件描述符創建兩個文件是否定義明確? (Is creating two FILEs for the same file descriptor well‑defined?)
POSIX 指定了一個 fdopen 函數,該函數為一個文件描述符。POSIX 還指定了一個 fileno 函數,該函數返回 FILE
。這兩者一起可用於創建第二個 FILE
訪問與現有文件相同的底層文件描述符:
FILE *secondfile(FILE *f, const char *mode)
{
int fd = fileno(f);
return fd >= 0 ? fdopen(fd, mode) : NULL;
}
這是 POSIX 下定義明確的操作嗎?當我訪問為同一個文件描述符創建的原始 FILE
和第二個 FILE
時會發生什麼?是否指定了交互?如果是,怎麼做?
從歷史上看,Unices 使用 FILE
結構的固定表來存儲您可以打開的 20 個文件。因此,對已與 FILE
關聯的文件描述符調用 fdopen()
會破壞現有文件並產生未定義的行為。我不確定 POSIX 是否仍然允許 stdio
的這種實現,這就是我問這個問題的原因。
參考解法
方法 1:
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.
方法 2:
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.
(by fuz、John Bollinger、Thomas Padron‑McCarthy)