在类似unix的系统上,尝试在文件描述符上调用write
函数有时会导致错误:
[EBADF] fildes is not a valid file descriptor open for writing.
这通常是在使用open
以及不包含O_WRONLY
或O_RDWR
的标记组合打开文件描述符时。
(参见man 2 open,man 2 write for more info)
所以,问题是:
在什么情况下永远有效与open
,O_APPEND
,O_TRUNC
中的任何一个调用O_CREAT
,而不通过其中一个写标志?
这是因为最近我遇到的问题是只传递O_APPEND
标志会成功打开文件,但是在fd上调用write
会导致EBADF
,因为我没有将O_RDONLY
以外的内容传递给open
来电。
如果标志的组合无效(例如open
没有任何写标志),我希望O_APPEND
失败并出现一些错误,但事实并非如此。这有什么理由,还是仅仅是历史posix标准的神器?
是否存在O_APPEND
+ O_RDONLY
是有效组合的情况?
答案 0 :(得分:2)
这取决于“有效”的含义。
AFAICT,POSIX没有具体提到这种标志组合。但确实说:
应用程序应指定前五个值中的一个(文件 访问模式)下面的oflag值:
- 了O_EXEC
- O_RDONLY
- O_RDWR
- O_SEARCH
- O_WRONLY
然后
并非所有标志组合都有意义。例如,使用O_SEARCH | O_CREAT将成功打开一个预先存在的搜索目录,但如果该名称没有现有文件,则不指定是否会创建常规文件。
根据POSIX,我会得出结论认为单独的O_APPEND属于“未指定”的行为(即,不要这样做)。
有关详细信息,请参阅此处:http://pubs.opengroup.org/onlinepubs/9699919799/
答案 1 :(得分:2)
我无法想到传递O_APPEND
和O_RDONLY
会产生与传递O_RDONLY
不同的任何情况。 SUSv4 seems to imply至少应该允许它。
对于O_TRUNC
,SUSv4在传递O_RDONLY
时没有指定行为:
未
O_TRUNC
或O_RDWR
使用O_WRONLY
的结果未定义。
fcntl()可以在描述符创建后更改状态标志,因此可能看起来像是一种方式,例如打开文件O_APPEND
时O_RDONLY
可能很重要。然而,
对应于文件访问模式的位和在< fcntl.h> 中定义的文件创建标志,在arg中设置的位应被忽略。如果应用程序更改了此处提到的arg中的任何位,则结果未指定
在Linux上,fcntl(2)
可以更改O_APPEND
,O_ASYNC
,O_DIRECT
,O_NOATIME
和O_NONBLOCK
标记,但不能更改会有所作为。这个讨论。
有点做作,但我想传递O_RDONLY | O_APPEND
可能会影响你fcntl(fd, F_GETFL, ...)
时得到的标志。虽然我还没有确认过。
至于为什么事情是这样设计的,我不知道。