int fcntl(int fd, int command, ... /* arg */ );
是否可移植:flags = fcntl(fd, F_GETFL);
(注意:没有arg
)?
F_GETFL (void)
Get the file access mode and the file status flags; arg
is ignored.
void
在Linux文档中表示不需要arg
。
这是usage example from POSIX for a related F_GETFD
flag:
#include <unistd.h>
#include <fcntl.h>
...
int flags;
flags = fcntl(fd, F_GETFD);
if (flags == -1)
/* Handle error */;
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1)
/* Handle error */;"
它表明arg
(今天)不需要F_GETFD
。然后它说:
F_GETFD,F_SETFD,F_GETFL和F_SETFL的arg值都代表 标志值以允许未来增长。
这是否意味着F_GETFL
将来可能会使用arg
?
快速搜索&#34; F_GETFL&#34;在Ohloh代码上创建一个most open-source projects do pass arg
(通常为0
,有时为NULL
,甚至(已损坏?)&fl
)的展示。我不明白为什么fcntl(fd, F_GETFL, 0)
是首选形式。 @Wumpus Q. Wumbley suggests "Advanced Programming in the UNIX Environment" book可能导致fcntl(fd, F_GETFL, 0)
形式的{{3}}。
是否有需要第3个arg的系统/编译器:flags = fcntl(fd, F_GETFL, 0);
? fcntl(fd, F_GETFL)
和fcntl(fd, F_GETFL, 0)
可以在今天或将来产生不同的结果(假设符合规定的实施)吗?
答案 0 :(得分:5)
查看其余的fcntl命令。注意它们中的一些(F_DUPFD,F_SETFL和其他)如何告诉你第三个arg用于什么。使用其中一个时,您需要提供第三个arg。不是在使用F_GETFL或F_GETFD时。
在大概中你可以看到fcntl需要2个args加上...
,这意味着当它不会被使用时可以省略第三个arg。
在做了一些研究后,我发现有一些旧的手册页(从第一个APUE开始),其中概要意味着所有3个参数都是必需的。示例:http://www.freebsd.org/cgi/man.cgi?query=fcntl&manpath=FreeBSD+2.2.7-RELEASE
SYNOPSIS
#include <fcntl.h>
int
fcntl(int fd, int cmd, int arg);
我无法找到任何证据表明它曾经在标题中实际声明过,但如果是这样的话,那么只用2个参数调用时编译就会失败。这将是在代码中包含额外0参数的一个很好的理由。
如果我的猜测是正确的,这是历史使用3-arg F_GETFL的真正原因那么它就是一个无用的化石,从功能原型是新的和可怕的操作系统供应商错误的时候开始。
答案 1 :(得分:2)
这两个电话
flags = fcntl(fd, F_GETFL);
flags = fcntl(fd, F_GETFL, 0);
是等效的,因为忽略了第三个可变参数。如果您查看fs/fcntl.c
:262和fs/fcntl.c
:269,您会看到arg
未使用。
但是,当您需要设置某个值时,您应该传递您想要设置的值
您可以将fcntl
视为等效于getter和setter的OOP。
是否有需要第3个arg的系统:flags = fcntl(fd,F_GETFL,0);?
我不知道。 Linux至少没有。文档明确指出它被忽略了,因为没有使用arg
。事实上你可以传递一些东西并不意味着你必须这样做。
fcntl(fd, F_GETFL)
和fcntl(fd, F_GETFL, 0)
可以在某个系统上返回不同的结果(在过去,今天和将来(假设符合要求的实施))?
lxr
允许我们深入研究旧版本的Linux,甚至在1991年,使用Linux 2.0.4,fcntl
传递了第三个参数。接受任何进一步的论证是没有意义的。因此,如果有一个系统,第三个参数有意义,那肯定不是Linux。
我做了一些进一步的研究,但我发现了一些相互矛盾的结果。请看here:有些书(我不会发布直接链接,因为它们可能是protected
),它们建议将fcntl
作为三个参数函数。但是,至少关于GETFL
/ GETFD
,没有提及arg
恕我直言,它的行为从未被认真对待过:那就是让你疑惑的原因。此外,我甚至认为使用第三个论点是有害的:如果它具有/将具有意义怎么办?
我再次通过Linux,这些命令的第三个参数永远不会通过。
最后
是否有系统/编译器需要第3个arg:flags = fcntl(fd,F_GETFL,0);? fcntl(fd,F_GETFL)和fcntl(fd,F_GETFL,0)可以在今天或将来产生不同的结果(假设是合规的实现)吗?
未来是个谜。今天我觉得足够肯定排除这一点。但是,在过去它可能已经如此。
答案 2 :(得分:2)
在FreeBSD基础系统中,使用了fcntl(fd, F_GETFL)
和fcntl(fd, F_GETFL, 0)
。但在大多数情况下,使用第三个参数0。这可能是出于历史原因,因为fcntl
可以追溯到4.2BSD,并且是通过4.4BSD-Lite源代码导入到FreeBSD中的。
在4.4BSD(和FreeBSD 2.0)中,手册页将参数列为mandatory:int fcntl(int fd, int cmd, int arg)
,即使实际的老派标题为not:{{1} }。
关于为什么,这很难回答。我们不得不问原作者。但由于原始源代码控制标记中没有记录(用户)名称,因此我不知道如何跟踪它们。
FreeBSD代码库中可能永远不会删除额外的0参数,因为它不会破坏任何内容,因此不足以解决&#34;修复&#34;。