POSIX 表示 stderr 应该对读写开放是什么意思?

What does POSIX mean when it says stderr is expected to be open for reading and writing?

POSIX 在 stderr, stdin, stdout - standard I/O streams 上的页面是这样说的:

The stderr stream is expected to be open for reading and writing.

"expected to be"有多强?违反它是未定义的行为吗?它是谁的责任,系统的还是应用程序的?

考虑这个程序:

#include <stdio.h>

int main(void) {
    printf("feof is %d and ferror is %d\n", feof(stderr), ferror(stderr));
    printf("fgetc is %d\n", fgetc(stderr));
    printf("feof is %d and ferror is %d\n", feof(stderr), ferror(stderr));
}

当我 运行 没有重定向 stderr(所以它就像 stdin 一样指向我的终端)时,它立即输出这个而不等待任何输入:

feof is 0 and ferror is 0
fgetc is -1
feof is 0 and ferror is 1

这是否意味着我的系统不 POSIX 兼容?

此外,如果这是我的责任,那么假设我有一个具有权限 620 的文件,并且我在组中但不是所有者。这是否意味着 someprogram 2>saidfile 是未定义的行为,因为在那种情况下无论如何您都无法从 stderr 读取?

POSIX 在 specification for execve 中对此进行了详细说明:

If file descriptor 0, 1, or 2 would otherwise be closed after a successful call to one of the exec family of functions, implementations may open an unspecified file for the file descriptor in the new process image. If a standard utility or a conforming application is executed with file descriptor 0 not open for reading or with file descriptor 1 or 2 not open for writing, the environment in which the utility or application is executed shall be deemed non-conforming, and consequently the utility or application might not behave as described in this standard.

对于您自己的应用程序,如果他们尝试在其中任何一个关闭的情况下执行,并且可以设置自己的规则(包括将其视为如果标准文件描述符在启动时未打开,则违反合同会导致灾难性的错误行为)如何处理。

对于标准实用程序,上面的文字涵盖了它。

document you cited 只是指定它们与那些文件描述符相关联。我同意它不够清楚,但合理的解释是,如果相应的文件描述符未打开或未打开应用程序入口处的适当模式,则结果是相关功能下为该条件(通常是 EBADF)指定的结果.例如,fgetc 指定:

[EBADF]

[CX] [Option Start] The file descriptor underlying stream is not a valid file descriptor open for reading. [Option End]

关于 "expected to be" 文本:

The stderr stream is expected to be open for reading and writing.

我不认为 "expected to be" 在标准中有任何定义。但是,这里使用的是 stream 一词,而不是 file/file-descriptor,因此我会将其解读为 FILE 模式(如 fopen 模式) stderr 流是这样的,只要遵守关于在它们之间切换的规则,其上的读取和写入函数都不会产生未定义的行为。没有这个文本,例如在顶部没有 POSIX 的情况下,fgetc(stderr) 可能会产生未定义的行为。

Austin Group (the joint working group that maintains the POSIX standard) discussed the defect that was reported about the "expected to be" wording during the 2020-12-07 and 2020-12-10 telecons and agreed that the wording in POSIX Issue 7 (2018 edition) is problematic. The wording will be changed in the next version of the POSIX standard as follows (copied from the bug comment):

On page 65 before line 1912 (XBD "interactive shell") insert a new definition and renumber the remaining:

Interactive Device

A terminal device.

Note: This definition is intended to align with the ISO C standard's use of "interactive device".

第 496 页第 17224-17228 行(XSH 2.5 标准 I/O 流)和第 2017 页第 64723-64727 行(XSH 标准错误、标准输入、标准输出描述)更改:

At program start-up, three streams shall be predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). When opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

至:

At program start-up, three streams shall be predefined and already open: stdin (standard input, for conventional input) for reading, stdout (standard output, for conventional output) for writing, and stderr (standard error, for diagnostic output) for writing. When opened, stderr shall not be fully buffered; stdin and stdout shall be fully buffered if and only if [CX]the file descriptor associated with the stream is determined not to be associated with an interactive device.[/CX]

在第 2017 页第 64733 行(XSH 标准输入描述)中,更改:

The stderr stream is expected to be open for reading and writing.

至:

These file descriptors are often all associated with a single open file description which has access mode O_RDWR (e.g., in the case of a terminal device for a login shell). However, the stderr, stdin, and stdout streams need not be opened for both reading and writing at program start-up in this case.

在第 2017 页第 64747 行(标准输入还请参见)添加 isatty()。

特别感谢 Rich Felker 报告缺陷。