Pregunta

Por lo que he estado leyendo en el sitio web de Open Group en fcntl , open , read , y write , me da la impresión de que si O_NONBLOCK se encuentra en un descriptor de archivo, y por lo tanto si no bloqueo de e / S se utiliza con el descriptor, debe ser una propiedad de ese archivo descriptor en lugar del archivo subyacente. Al ser una propiedad de los medios de descriptor de archivo, por ejemplo, que si duplico un descriptor de archivo o abrir otro descriptor en el mismo archivo, entonces puedo usar el bloqueo de E / S con uno y sin bloqueo de E / S con la otra.

La experimentación con un FIFO, sin embargo, parece que no es posible tener un descriptor de bloqueo de E / S y no bloqueante descriptor de E / S a la FIFO al mismo tiempo (por lo que si O_NONBLOCK es conjunto es una propiedad del archivo subyacente [la 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;
}

Esto me deja pensando: ¿Alguna vez es posible tener un descriptor de no bloqueo de E / S y el bloqueo de E / S descriptor en el mismo archivo y si es así, de qué depende el tipo de archivo (archivo regular, FIFO, bloquear el archivo especial, fichero especial de caracteres, zócalo, etc.)?

¿Fue útil?

Solución

O_NONBLOCK es una propiedad de la descripción de archivo abierto, no del descriptor de archivo, ni de archivos subyacente.

Sí, usted podría tener descriptores de archivos independientes abren para el mismo archivo, uno de los cuales está bloqueando y el otro de los cuales es no bloqueante.

Es necesario distinguir entre una FIFO (creada usando mkfifo() ) y un tubo (creado usando pipe() ).

Tenga en cuenta que el estado de bloqueo es una propiedad de la 'descripción de archivo abierto', pero en los casos más simples, hay una correlación uno a uno entre los descriptores de fichero y descripción de archivos abiertos. El open() llamada a la función crea una nueva descripción de archivo abierto y un nuevo descriptor de archivo que se refiere a la descripción de archivo abierto.

Cuando se utiliza dup() , tiene dos descriptores de archivos que comparten un descripción de archivo abierto, y las propiedades pertenecen a la descripción de archivo abierto. La descripción de fcntl() dice que F_SETFL afecta a la descripción de archivo abierto asociado con el descriptor de archivo. Tenga en cuenta que lseek() ajusta la posición de archivo de la descripción de archivo abierto asociado con el descriptor de archivo -. por lo que afecta a otros descriptores de archivos duplicados del original

La eliminación de la manipulación de su código para reducirlo error, usted tiene:

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

Ahora ambos fd0_dup y fds [0] se refieren a la misma descripción de archivo abierto (debido a la dup()), por lo que la operación fcntl() afectó a ambos descriptores de archivos.

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

Por lo tanto, el comportamiento observado aquí es requerido por POSIX.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top