когда требуется аргумент для команды F_GETFL fcntl?
Вопрос
int fcntl(int fd, int command, ... /* arg */ );
Является ли это портативным: flags = fcntl(fd, F_GETFL);
(примечание:НЕТ arg
)?
И то, и другое Linux и FreeBSD справочные страницы говорят, что arg
игнорируется:
F_GETFL (void)
Get the file access mode and the file status flags; arg
is ignored.
void
в документации Linux это означает, что arg
не требуется.
Вот такой пример использования из POSIX для связанного F_GETFD
Отметить:
#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 представляют собой значения флагов для обеспечения будущего роста.
Подразумевает ли это , что F_GETFL
мог бы использовать arg
в будущем?
Быстрый поиск "F_GETFL" в коде Ohloh создает впечатление, что большинство проектов с открытым исходным кодом действительно проходят arg
(обычно 0
, иногда NULL
, или даже (сломанный?) &fl
).Я не понимаю, почему fcntl(fd, F_GETFL, 0)
является предпочтительной формой. @Вумпус В.Вамбли предлагает что это может быть вызвано книга "Расширенное программирование в среде UNIX" это также использует fcntl(fd, F_GETFL, 0)
форма.
Существует ли система / компилятор, для которого требуется 3-й аргумент: flags = fcntl(fd, F_GETFL, 0);
?Может fcntl(fd, F_GETFL)
и fcntl(fd, F_GETFL, 0)
дают разные результаты сегодня или в будущем (при условии соответствующей реализации)?
Решение
Посмотрите на остальные команды fcntl.Обратите внимание, как некоторые из них (F_DUPFD, F_SETFL и другие) сообщают вам, для чего используется третий аргумент.Вам необходимо указать третий аргумент при использовании одного из них.Не при использовании F_GETFL или F_GETFD.
В КРАТКОМ ОБЗОРЕ вы можете видеть, что fcntl принимает 2 аргумента плюс ...
это означает, что третий аргумент может быть опущен, если он не будет использоваться.
Проведя еще некоторое исследование, я обнаружил, что есть несколько старых справочных страниц (примерно со времен первого APUE), в которых КРАТКИЙ ОБЗОР подразумевает, что требуются все 3 аргумента.Пример: http://www.freebsd.org/cgi/man.cgi ?запрос=fcntl&manpath=FreeBSD+2.2.7-РЕЛИЗ
SYNOPSIS
#include <fcntl.h>
int
fcntl(int fd, int cmd, int arg);
Я не могу найти никаких доказательств того, что это когда-либо действительно было объявлено таким образом в заголовке, но если бы это было так, то компиляция завершилась бы неудачей, если бы она была вызвана только с 2 аргументами.Это было бы хорошей причиной включить дополнительный аргумент 0 в ваш код.
Если мое предположение верно, и это фактическая причина исторического использования F_GETFL с 3 аргументами, то это бесполезное ископаемое того времени, когда прототипы функций были новыми и пугающими, а поставщики ОС ошибались в них.
Другие советы
В базовой системе FreeBSD оба fcntl(fd, F_GETFL)
и fcntl(fd, F_GETFL, 0)
используются.Но в большинстве случаев используется третий аргумент 0.Это могло быть вызвано историческими причинами, поскольку fcntl
восходит к версии 4.2BSD и был импортирован во FreeBSD с помощью исходного кода 4.4BSD-Lite.
В версии 4.4BSD (и FreeBSD 2.0) на странице руководства аргумент указан как обязательный: int fcntl(int fd, int cmd, int arg)
, даже несмотря на то , что фактический заголовок старой школы делает не: int fcntl(int, int, ...)
.
Что касается почему, на это будет трудно ответить.Нам пришлось бы спросить первоначального автора (ов).Но поскольку в исходных тегах управления версиями нет имен пользователей, я бы не знал, как их отследить.
Дополнительный аргумент 0, вероятно, никогда не удалялся из кодовой базы FreeBSD, потому что он ничего не нарушает и поэтому недостаточно важен для "исправления".
Эти два звонка
flags = fcntl(fd, F_GETFL);
flags = fcntl(fd, F_GETFL, 0);
эквивалентны, поскольку третий переменный параметр игнорируется.Если вы взглянете на fs/fcntl.c
:262 и fs/fcntl.c
:269 вы увидите, что arg
не используется.
Однако, когда вам нужно установить какое-то значение, вы должны передать значение, которое вы хотите установить.
Вы могли бы рассмотреть fcntl
как ООП-эквивалент геттеров и сеттеров.
Существует ли система, для которой требуется 3-й аргумент:флаги = 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.
Я провел кое-какие дальнейшие исследования и обнаружил несколько противоречивых результатов.Посмотрите на здесь:есть несколько книг (я не размещаю прямую ссылку на них, поскольку они могли бы быть protected
) которые действительно предлагают fcntl
как функция с тремя аргументами.Но, по крайней мере, в отношении GETFL
/GETFD
, не упоминается о arg
.
ИМХО, его поведение никогда не воспринималось всерьез:то есть то, что заставляет вас задуматься.Более того, я бы даже счел вредным использовать этот третий аргумент:что, если это имеет / будет иметь значение?
Я снова прошелся по Linux, и третий аргумент для этих команд так и не был передан.
Наконец - то
Существует ли система / компилятор, для которого требуется 3-й аргумент:флаги = fcntl(fd, F_GETFL, 0);?Могут ли fcntl(fd, F_GETFL) и fcntl(fd, F_GETFL, 0) давать разные результаты сегодня или в будущем (при условии совместимой реализации)?
Будущее - это тайна.Сегодня я чувствую себя достаточно уверенно, чтобы исключить это.Однако в прошлом это мог бы было бы так.