2011-10-22 49 views
17

Sé que dup, dup2, dup3 "crea una copia del descriptor de archivo oldfd" (de las páginas man). Sin embargo, no puedo digerirlo.¿Alguien puede explicar qué hace dup() en C?

Como sé, los descriptores de archivo son solo números para realizar un seguimiento de las ubicaciones de los archivos y su dirección (entrada/salida). ¿No sería más fácil simplemente

fd=fd2; 

¿Siempre que queremos duplicar un descriptor de archivo?

Y algo más ..

dup() utiliza el descriptor sin usar el número más bajo para el nuevo descriptor.

¿Eso significa que también se puede tomar como valor de entrada estándar , stdout o stderr si asumimos que tenemos close() -ed uno de esos?

+3

Por primera pregunta que hay que recordar que el núcleo no pierde de vista el número de abrir archivos de archivos. 'dup' es tu forma de decirle al kernel que quieres que mantenga un seguimiento de otro de esos manejadores de archivo (refiriéndose al mismo archivo) hasta que' lo cierres '. – user786653

Respuesta

12

Solo quería responderme a mí mismo en la segunda pregunta después de experimentar un poco.

La respuesta es . Un descriptor de archivo que realice puede tomar un valor 0, 1, 2 si stdin, stdout o stderr están cerrados.

Ejemplo:

close(1);  //closing stdout 
newfd=dup(1); //newfd takes value of least available fd number 

Cuando esto sucede a presentar descriptores:

0 stdin  .--------------.  0 stdin  .--------------.  0 stdin 
1 stdout =| close(1) :=> 2 stderr =| newfd=dup(1) :=> 1 newfd 
2 stderr '--------------'     '--------------'  2 stderr 
+1

Una pregunta surgió de nuevo: ¿cómo puedo 'dup()' un descriptor de archivo que ya cerré? – Pithikos

+0

De la definición, dup() usa el descriptor no utilizado con el número más bajo para el nuevo descriptor. Y cuando cierra un descriptor de archivo, esto significa que está disponible para su uso. –

2

ver este page, la salida estándar puede tener un alias como dup(1) ...

+0

+1. impresionante enlace –

5

Digamos que usted está escribiendo un programa de shell y desea redirigir entrada y salida estándar en un programa que desea ejecutar. Podría ser algo como esto:

fdin = open(infile, O_RDONLY); 
fdout = open(outfile, O_WRONLY); 
// Check for errors, send messages to stdout. 
... 
int pid = fork(0); 
if(pid == 0) { 
    close(0); 
    dup(fdin); 
    close(fdin); 
    close(1); 
    dup(fdout); 
    close(fdout); 
    execvp(program, argv); 
} 
// Parent process cleans up, maybe waits for child. 
... 

dup2() es un poco más conveniente hacerlo de la DUP close()() puede ser reemplazado por:

dup2(fdin, 0); 
dup2(fdout, 1); 

La razón por la que desea para hacer esto es que desea informar errores a stdout (o stderr) por lo que no puede simplemente cerrarlos y abrir un nuevo archivo en el proceso secundario. En segundo lugar, sería un desperdicio hacer el fork si cualquiera de las llamadas a open() devolviera un error.

9

Un descriptor de archivo es un poco más que un número. También lleva consigo varios estados semicubiertos (ya sea que estén abiertos o no, a qué descripción de archivo se refiere, y también algunos indicadores). dup duplica esta información, por lo que puede, p. cierra los dos descriptores de forma independiente. fd=fd2 no.

+1

Esto. El "número" es un índice en una estructura de datos mantenida por el kernel. La familia de funciones 'dup' clona el estado de un nodo en esa estructura de datos y le entrega el índice al nuevo nodo. – dmckee

+3

@dmckee: "Kernel" e "index" son detalles de implementación. Hay algunos datos asociados con "el número" que no pueden ser manipulados directamente por el programa, y ​​que son clonados por 'dup()'. Eso es todo lo que el programador necesita saber. Por cierto, no es un dato muy interesante, solo se trata de un par de indicadores y un índice de los datos realmente interesantes (la descripción del archivo abierto) que ** no ** clonó por 'dup()'. –

5

Lo más importante acerca de la duplicación() es que devuelve el entero más pequeño disponible para un nuevo descriptor de archivo.Esa es la base de la redirección:

int fd_redirect_to = open("file", O_CREAT); 
close(1); /* stdout */ 
int fd_to_redirect = dup(fd_redirect_to); /* magically returns 1: stdout */ 
close(fd_redirect_to); /* we don't need this */ 

Después de esto nada escrito para el descriptor de archivo 1 (stdout), mágicamente entra en "archivo".

+0

Suponiendo (no irrazonablemente) que el descriptor de archivo 0 está actualmente abierto. El soporte para redirecciones como '200> somefile' es muy inconveniente sin' dup2() '(o' dup3() ', pero eso es una adición reciente a los sistemas). –

0

Solo un consejo sobre "que duplica la salida estándar".

algunas versiones de Unix (pero no de GNU/Linux)

fd = open("/dev/fd/1", O_WRONLY); 

es equivalente a:

fd = dup(1); 
Cuestiones relacionadas