c file unix system-calls dup

ejemplos prácticos usan dup o dup2



file unix (5)

Cuando tenga curiosidad sobre las funciones de POSIX, especialmente aquellas que parecen duplicarse, generalmente es bueno verificar el estándar en sí . En la parte inferior, generalmente verá ejemplos, así como también el razonamiento detrás de la implementación (y existencia) de ambos.

En este caso:

Las siguientes secciones son informativas.

Ejemplos

Redirigir salida estándar a un archivo

El siguiente ejemplo cierra la salida estándar para los procesos actuales, reasigna la salida estándar para ir al archivo al que hace referencia la pfd y cierra el descriptor original del archivo para limpiar.

#include <unistd.h> ... int pfd; ... close(1); dup(pfd); close(pfd); ...

Redirigir mensajes de error

El siguiente ejemplo redirige mensajes de stderr a stdout .

#include <unistd.h> ... dup2(2, 1); // 2-stderr; 1-stdout ...

Uso de la aplicación

Ninguna.

Razón fundamental

Las funciones dup() y dup2() son redundantes. Sus servicios también son provistos por la función fcntl() . Se han incluido en este volumen de IEEE Std 1003.1-2001 principalmente por razones históricas, ya que muchas aplicaciones existentes los usan.

Si bien el breve segmento de código que se muestra es muy similar en comportamiento a dup2() , una implementación conforme basada en otras funciones definidas en este volumen de IEEE Std 1003.1-2001 es significativamente más compleja. Menos obvio es el posible efecto de una función de captura de señal que podría invocarse entre pasos y asignar o desasignar descriptores de archivos. Esto podría evitarse bloqueando las señales.

La función dup2() no está marcada como obsoleta porque presenta una versión de tipo seguro de la funcionalidad provista en una versión insegura por fcntl() . Se usa en el enlace POSIX Ada.

La función dup2() no está diseñada para ser utilizada en regiones críticas como un mecanismo de sincronización.

En la descripción de [EBADF], el caso de que los filtros estén fuera de rango está cubierto por el caso dado de que los filtros no son válidos. Las descripciones para fildes y fildes2 son diferentes porque el único tipo de invalidez que es relevante para fildes2 es si está fuera de rango; es decir, no importa si fildes2 hace referencia a un archivo abierto cuando se realiza la llamada dup2() .

Direcciones futuras

Ninguna.

Ver también

close() , fcntl() , open() , el volumen de Definiciones fcntl() de IEEE Std 1003.1-2001, <unistd.h>

cambia la historia

Publicado por primera vez en el Issue 1. Derivado del Issue 1 del SVID.

Sé lo que hace dup / dup2 , pero no tengo idea de cuándo se usaría.

¿Algún ejemplo práctico?

Gracias.


El mejor escenario para entender dup y dup2 es la redirección.
Lo primero que debemos saber es que el sistema tiene 3 identificadores de archivos predeterminados (o variables que indican salidas o fuentes de entrada) que se ocupan de la entrada y la salida. Son stdin , stdout , stderr , en enteros son 0 , 1 , 2 . La mayoría de las funciones como fprintf o cout se envían directamente a stdout .
Si queremos redirigir la salida, una forma es dar, por ejemplo, la función fprintf más argumentos que indiquen entrada y out .
Sin embargo, hay una manera más elegante: podemos sobrescribir los identificadores de archivos predeterminados para que apunten al archivo que queremos que reciba la salida. dup y dup2 funcionan exactamente en esta situación.
Comencemos con un ejemplo simple ahora: supongamos que queremos redirigir la salida de fprintf a un archivo txt llamado "chinaisbetter.txt". Antes que nada debemos abrir este archivo

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

Entonces queremos que stdout apunte a "chinaisbetter.txt" usando la función dup:

dup2(fw,1);

Ahora stdout (1) apunta al descriptor de "chinaisbetter.txt" aunque todavía es 1, pero la salida se redirige ahora.
Luego puede usar printf como de costumbre, pero los resultados estarán en el archivo txt en lugar de mostrarse directamente en la pantalla:

printf("Are you kidding me? /n");

PD :

  1. Esto solo da una explicación intuitiva, puede que necesite verificar la página de manual o información detallada. En realidad, decimos "copiar" aquí, no están copiando todo.

  2. La identificación del archivo aquí se refiere al manejador del archivo. El descriptor de archivo mencionado anteriormente es una estructura de la información del archivo de registros.


La redirección de E / S en el shell probablemente se implementaría usando llamadas al sistema dup2 / fcnlt.

Podemos $program 2>&1 > logfile.log tipo de redirección $program 2>&1 > logfile.log utilizando la función dup2.

El siguiente programa redirige tanto stdout como stderr .ie emula el comportamiento de $program 2>&1 > output utilizando dup2.

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> int main(void){ int close_this_fd; dup2(close_this_fd = open("output", O_WRONLY), 1); dup2(1,2); close(close_this_fd); fprintf(stdout, "standard output/n"); fprintf(stderr, "standard error/n"); fflush(stdout); sleep(100); //sleep to examine the filedes in /proc/pid/fd level. return; } vagrant@precise64:/vagrant/advC$ ./a.out ^Z [2]+ Stopped ./a.out vagrant@precise64:/vagrant/advC$ cat output standard error standard output vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd total 0 dr-x------ 2 vagrant vagrant 0 Jun 20 22:07 ./ dr-xr-xr-x 8 vagrant vagrant 0 Jun 20 22:07 ../ lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0 l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output


Un ejemplo de uso sería la redirección de E / S. Para esto, bifurca un proceso hijo y cierra los descriptores stdin o stdout (0 y 1) y luego realiza un dup () en otro descriptor de archivo de su elección que ahora se mapeará al descriptor de archivo más bajo disponible, que está en este caso 0 o 1.

Al usar esto, ahora puede ejecutar cualquier proceso secundario que posiblemente no tenga conocimiento de su aplicación y siempre que el niño escriba en stdout (o lea desde stdin, sea lo que sea que haya configurado), los datos se escribirán en el descriptor de archivo proporcionado.

Los proyectiles usan esto para implementar comandos con tuberías, por ejemplo, /bin/ls | more /bin/ls | more conectando el stdout de un proceso al stdin del otro.


Un ejemplo práctico es redirigir mensajes de salida a alguna otra secuencia, como algún archivo de registro. Aquí hay un código de muestra para la redirección de E / S.
Por favor, consulte la publicación original here

#include <stdio.h> main() { int fd; fpos_t pos; printf("stdout, "); fflush(stdout); fgetpos(stdout, &pos); fd = dup(fileno(stdout)); freopen("stdout.out", "w", stdout); f(); fflush(stdout); dup2(fd, fileno(stdout)); close(fd); clearerr(stdout); fsetpos(stdout, &pos); /* for C9X */ printf("stdout again/n"); } f() { printf("stdout in f()"); }