dup2 / dup: ¿por qué tendría que duplicar un descriptor de archivo?

7 minutos de lectura

dup2 dup ¿por que tendria que duplicar un descriptor
ENE

Estoy tratando de entender el uso de dup2 y dup.

De la página del manual:

DESCRIPTION

dup and dup2 create a copy of the file descriptor oldfd.
After successful return of dup or dup2, the old and new descriptors may
be used interchangeably. They share locks, file position pointers and
flags; for example, if the file position is modified by using lseek on
one of the descriptors, the position is also changed for the other.

The two descriptors do not share the close-on-exec flag, however.

dup uses the lowest-numbered unused descriptor for the new descriptor.

dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.  

RETURN VALUE

dup and dup2 return the new descriptor, or -1 if an error occurred 
(in which case, errno is set appropriately).  

¿Por qué necesitaría esa llamada al sistema? ¿De qué sirve duplicar el descriptor del archivo?

Si tengo el descriptor de archivo, ¿por qué querría hacer una copia de él?

Agradecería si pudieras explicarme y darme un ejemplo donde dup2 / dup se necesita

Gracias

  • ¿Cómo implementaría la funcionalidad de canalización de las conchas sin dup o dup2 ? tienes que llamar pipe(2) y luego tener uno de los descriptores de archivo dup-ed a, por ejemplo STDIN_FILENO

    – Basile Starynkevitch

    24 de julio de 2012 a las 23:52

  • Posible duplicado de ejemplos prácticos use dup o dup2

    – DraTyrsa

    20 de enero de 2017 a las 10:27

1647588428 793 dup2 dup ¿por que tendria que duplicar un descriptor
Pensamiento profundo

La llamada al sistema dup duplica un descriptor de archivo existente y devuelve uno nuevo que hace referencia al mismo objeto de E/S subyacente.

Dup permite que los shells implementen comandos como este:

ls existing-file non-existing-file > tmp1  2>&1

El 2>&1 le dice al shell que le dé al comando un descriptor de archivo 2 que es un duplicado del descriptor 1. (es decir, stderr y stdout apuntan al mismo fd).
Ahora el mensaje de error para llamar ls en archivo inexistente y la salida correcta de ls en archivo existente aparecer en tmp1 expediente.

El siguiente código de ejemplo ejecuta el programa wc con una entrada estándar conectada al extremo de lectura de una tubería.

int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = 0;
pipe(p);
if(fork() == 0) {
    close(STDIN); //CHILD CLOSING stdin
    dup(p[STDIN]); // copies the fd of read end of pipe into its fd i.e 0 (STDIN)
    close(p[STDIN]);
    close(p[STDOUT]);
    exec("/bin/wc", argv);
} else {
    write(p[STDOUT], "hello world\n", 12);
    close(p[STDIN]);
    close(p[STDOUT]);
}

El niño duplica el final de lectura en el descriptor de archivo 0, cierra los descriptores de archivo en p y ejecuta wc. Cuando wc lee desde su entrada estándar, lee desde la tubería.
Así es como se implementan las tuberías usando dup, bueno, un uso de dup ahora usa tubería para construir otra cosa, esa es la belleza de las llamadas al sistema, construyes una cosa tras otra usando herramientas que ya están ahí, estas herramientas fueron construidas a su vez usando algo más, etc. Al final, las llamadas al sistema son las herramientas más básicas que obtienes en el kernel

Salud 🙂

  • Entoncesdup es útil para la persona que llama y no para el ls programa en si? ¿Hay algún beneficio de tener dup ¿Se usa en un programa como ls si ya tiene acceso al archivo? Aquí por ejemplo, ls escribe errores a 2 que está codificado, por lo que tengo una forma de anularlo como consumidor de ls. Creo que eso es un punto sutil, ¿no?

    – Nishant

    28 de marzo de 2016 a las 11:29


  • Tu programa de ejemplo parece tener un error; estás llamando dup(p[STDIN]) pero luego tirar el resultado. ¿Querías usar dup2(p[STDIN], 0)?

    – Quuxplusone

    8 de agosto de 2017 a las 18:27

  • @Quuxplusone dup devuelve el “descriptor con el número más bajo que el proceso no utiliza actualmente”. Dado que fd 0 acaba de cerrarse, dup debería devolver 0. dup2 es explícito sobre qué fd debe usarse, en lugar de solo usar el fd libre más bajo, por lo que preferiría eso.

    – Wodin

    28 de diciembre de 2017 a las 5:14

  • @Wodin: Ah, apuesto a que tienes razón sobre lo que OP estaba pensando. Sin embargo, ¿también tengo razón en que “recién cerrado” es relativo, y el código de OP podría romperse en presencia de, por ejemplo, subprocesos simultáneos que también podrían estar abriendo archivos?

    – Quuxplusone

    28 de diciembre de 2017 a las 17:48

  • @Wodin JFI: con dup2 no llamarías close antes de.

    – azulado

    20 de febrero de 2020 a las 15:44

Otra razón para duplicar un descriptor de archivo es usarlo con fdopen. fclose cierra el descriptor de archivo que se pasó a fdopenpor lo que si no desea que se cierre el descriptor de archivo original, debe duplicarlo con dup primero.

  • fdopen() parece que no duplica un descriptor de archivo, solo crea un búfer en el espacio del usuario.

    –Eric

    5 de mayo de 2015 a las 5:11

  • Leíste mal mi respuesta. El punto es que usted puede querer dup el fd antes de pasarlo a fdopen ya que fclose lo cerrará.

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 mayo 2015 a las 15:30

  • @theferrit32: si asigna un FILE manejar para acceder a un archivo abierto preexistente a través de las interfaces de stdio, debe llamar fclose desasignar eso FILE encargarse de. Si desea seguir utilizando el archivo abierto subyacente, o si su arquitectura de software es tal que el código de “propietario” original para el descriptor de archivo close eso, el hecho de que fclose también cierra el descriptor de archivo subyacente que le entregó a fdopen es un problema. Puedes evitar este problema usando dup para hacer un nuevo descriptor de archivo para el mismo archivo abierto para pasar a fdopenasí que eso fclose no cierra el original.

    – R.. GitHub DEJA DE AYUDAR A ICE

    1 de noviembre de 2018 a las 2:33

  • El punto es que fdopen() se mueve propiedad de la fd a la FILEen vez de proceso de copiar eso. Eso es algo que los usuarios deben tener en cuenta. Consumidores que necesitan retener un usable fd manejar además del FILE el objeto debe duplicar el fd. Eso es todo.

    –Conrado Meyer

    18 de marzo de 2020 a las 18:16

  • @ConradMeyer: Sí, esa es una muy buena manera de decirlo, con una nota de que no hay ninguna operación para “mover la propiedad” fuera del FILE una vez que le transfieres la propiedad.

    – R.. GitHub DEJA DE AYUDAR A ICE

    18 de marzo de 2020 a las 18:50

dup se utiliza para poder redirigir la salida de un proceso.

Por ejemplo, si desea guardar el resultado de un proceso, duplica el resultado (fd=1), redirige el fd duplicado a un archivo, luego bifurca y ejecuta el proceso, y cuando finaliza, redirige nuevamente el fd guardado en la salida.

Se pueden observar algunos puntos relacionados con dup/dup2, por favor

dup/dup2: técnicamente, el propósito es compartir una entrada de la tabla de archivos dentro de un proceso único por diferentes mangos. (Si estamos bifurcando, el descriptor se duplica de forma predeterminada en el proceso secundario y la entrada de la tabla de archivos también se comparte).

Eso significa que podemos tener más de un descriptor de archivo que tenga atributos posiblemente diferentes para una sola entrada de tabla de archivos abiertos usando la función dup/dup2.

(Aunque parece que actualmente solo el indicador FD_CLOEXEC es el único atributo para un descriptor de archivo).

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

dup(fd) is equivalent to fcntl(fd, F_DUPFD, 0);

dup2(fildes, fildes2); is equivalent to 

   close(fildes2);
   fcntl(fildes, F_DUPFD, fildes2);

Las diferencias son (por último)- Aparte de algún valor errno entre dup2 y fcntl close seguido de fcntl puede generar condiciones de carrera ya que están involucradas dos llamadas de función.

Los detalles se pueden consultar desde
http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

Un ejemplo de uso

Un ejemplo interesante al implementar el control de trabajos en un shell, donde se puede ver el uso de dup/dup2… en el siguiente enlace

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad