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 :
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.
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()");
}