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

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

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

#include 
#include 
#include 
#include 
#include 

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, блок специальный файл, символьный специальный файл, сокет, и т.д.)?

19
задан Daniel Trebbien 22 May 2010 в 21:53
поделиться

1 ответ

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.

28
ответ дан 30 November 2019 в 04:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: