Это O_NONBLOCK устанавливает свойство дескриптора файла или базового файла?

StackOverflow https://stackoverflow.com/questions/2889901

Вопрос

От того, что я читал на веб-сайте открытой группы на fcntl, open, read, а также write, Я создаю впечатление, что O_NONBLOCK Установлено на файловом дескриптере и, следовательно, используется ли неблокирующий ввод / вывод с дескриптором, должен быть свойством этого файлового дескриптора, а не базовый файл. Будучи свойством дескриптора файлового дескриптора, например, что, если я дублирую файловый дескриптор или открываю другой дескриптор в тот же файл, то я могу использовать блокировку ввода / вывода с одним и безблокировкой ввода-вывода с другой.

Экспериментируя с FIFO, однако, похоже, что невозможно иметь блокирующее дескриптор ввода / вывода и неблокирующего дескриптор ввода / вывода в FIFO одновременно (так что O_NONBLOCK Настройка является свойством базового файла [FIFO]):

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int fds[2];
    if (pipe(fds) == -1) {
        fprintf(stderr, "`pipe` failed.\n");
        return EXIT_FAILURE;
    }

    int fd0_dup = dup(fds[0]);
    if (fd0_dup <= STDERR_FILENO) {
        fprintf(stderr, "Failed to duplicate the read end\n");
        return EXIT_FAILURE;
    }

    if (fds[0] == fd0_dup) {
        fprintf(stderr, "`fds[0]` should not equal `fd0_dup`.\n");
        return EXIT_FAILURE;
    }

    if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) {
        fprintf(stderr, "`fds[0]` should not have `O_NONBLOCK` set.\n");
        return EXIT_FAILURE;
    }

    if (fcntl(fd0_dup, F_SETFL, fcntl(fd0_dup, F_GETFL) | O_NONBLOCK) == -1) {
        fprintf(stderr, "Failed to set `O_NONBLOCK` on `fd0_dup`\n");
        return EXIT_FAILURE;
    }

    if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) {
        fprintf(stderr, "`fds[0]` should still have `O_NONBLOCK` unset.\n");
        return EXIT_FAILURE; // RETURNS HERE
    }

    char buf[1];
    if (read(fd0_dup, buf, 1) != -1) {
        fprintf(stderr, "Expected `read` on `fd0_dup` to fail immediately\n");
        return EXIT_FAILURE;
    }
    else if (errno != EAGAIN) {
        fprintf(stderr, "Expected `errno` to be `EAGAIN`\n");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Это оставляет меня задуматься: это возможно ли когда-либо иметь неблокирующий дескриптор ввода / вывода и блокируя дескриптор ввода / вывода в тот же файл, и если это так, зависит от типа файла (обычный файл, FIFO, Block Special file , персонаж специальный файл, розетка и т. Д.)?

Это было полезно?

Решение

O_NONBLOCK - это свойство описания открытого файла, а не дескриптора файла, ни базового файла.

Да, вы могли бы иметь отдельные файловые дескрипторы, открытые для одного и того же файла, один из которых блокируется, а другой из которых не блокируется.

Вам нужно различить FIFO (созданное с использованием mkfifo()) и труба (созданная с использованием pipe()).

Обратите внимание, что состояние блокировки представляет собой свойство «Описание файла открытого файла», но в самых простых случаях существует однозначное отображение между дескрипторами файлов и открытыми описаниями файлов. То open() Функциональный вызов создает новое описание открытого файла и новый дескриптор файла, который относится к описанию открытого файла.

Когда вы используете dup(), у вас есть два файловых дескрипторов, которые разделяют одно открытое описание файла, а свойства принадлежат описанию открытого файла. Описание fcntl() Говорит, что F_SetFL влияет на описание открытого файла, связанного с дескриптором файла. Обратите внимание, что lseek() Регулирует положение файла описания открытого файла, связанного с дескриптором файла - поэтому он влияет на другие дескрипторы файлов, дублированные из оригинального.

Удаление обработки ошибок от вашего кода, чтобы уменьшить его, у вас есть:

int fds[2];
pipe(fds);
int fd0_dup = dup(fds[0]);
fcntl(fd0_dup, F_SETFL, fcntl(fd0_dup, F_GETFL) | O_NONBLOCK);

Теперь FD0_DUP и FDS [0] относятся к одному и тому же описанию файла открытого файла (из-за dup()), Итак fcntl() Работа поражена как файловых дескрипторов.

if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) { ... }

Следовательно, наблюдаемое поведение здесь требуется по POSIX.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top