dup2 / dup - ¿por qué necesitaría duplicar un descriptor de archivo?


Estoy tratando de entender el uso de dup2 y dup.

De la página de 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 de archivo?

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

Le agradecería si pudiera explicarme y darme un ejemplo donde dup2 / dup es necesario.

Gracias

Author: Matheus Santana, 2012-07-24

4 answers

La llamada al sistema dup duplica un descriptor de archivo existente, devolviendo uno nuevo que se refiere al mismo objeto de E/S subyacente.

Dup permite a los shells implementar comandos como este:

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

2>&1 le dice al shell que le dé a la orden 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 a ls en archivo que no exista y la salida correcta de ls en existente el archivo aparece en el archivo tmp1.

El siguiente código de ejemplo ejecuta el programa wc con entrada estándar conectada al fin leído del tubo.

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 hijo dups el final de lectura en el descriptor de archivo 0, cierra el archivo de scriptors en p, y execs wc. Cuando wc lee de su entrada estándar, lee de la tubo.
Así es como se implementan las tuberías usando dup, así que un uso de dup ahora usas tubería para construir algo más, esa es la belleza de las llamadas al sistema, construir una cosa tras otra utilizando herramientas que ya están allí, estas herramientas fueron inturn construido usando algo más así sucesivamente .. Al final, las llamadas al sistema son las herramientas más básicas que obtienes en kernel

Saludos:)

 33
Author: Deepthought,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-08 09:12:25

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

 15
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-24 17:53:09

Algunos puntos relacionados con dup / dup2 se pueden señalar por favor

Dup/dup2 - Técnicamente el propósito es compartir una Entrada de tabla de archivos dentro de un proceso único por diferentes manejadores. (Si estamos bifurcando el descriptor se duplica por defecto en el proceso hijo 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 abierta utilizando dup / dup2 función.

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

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 (para el último)- Aparte de algún valor errno entre dup2 y fcntl close seguido por fcntl puede elevar las condiciones de carrera ya que dos llamadas de función están involucradas.

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

Un Ejemplo de uso -

Un ejemplo interesante al implementar control de tareas en un shell, donde se puede ver el uso de dup/dup2 in en el enlace de abajo

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

 4
Author: Tanmoy Bandyopadhyay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-24 19:01:43

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

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

 3
Author: alinsoar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-24 16:27:53