什么时候需要F_GETFL fcntl命令的arg?

时间:2014-07-31 14:35:10

标签: c linux unix freebsd fcntl

int fcntl(int fd, int command, ... /* arg */ );

是否可移植:flags = fcntl(fd, F_GETFL);(注意:没有arg)?

LinuxFreeBSD手册页都说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)可以在今天或将来产生不同的结果(假设符合规定的实施)吗?

3 个答案:

答案 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:262fs/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)中,手册页将参数列为mandatoryint fcntl(int fd, int cmd, int arg),即使实际的老派标题为not:{{1} }。

关于为什么,这很难回答。我们不得不问原作者。但由于原始源代码控制标记中没有记录(用户)名称,因此我不知道如何跟踪它们。

FreeBSD代码库中可能永远不会删除额外的0参数,因为它不会破坏任何内容,因此不足以解决&#34;修复&#34;。