esempi pratici utilizzano duplicazione o dup2
-
19-09-2019 - |
Domanda
dup
/ dup2
fa, ma ho nessuna idea di quando sarebbe stato utilizzato.
Qualsiasi esempi pratici?
Grazie.
Soluzione
Un esempio potrebbe essere l'uso redirezione I / O. Per questo fork di un processo figlio e aver chiuso i descrittori di file stdin o stdout (0 e 1) e poi si fa un DUP () su un altro filedescriptor a tua scelta che sarà ora associato al più basso descrittore di file disponibile, che è in questo caso 0 o 1.
Con questo è ora possibile exec qualsiasi processo figlio che è forse a conoscenza della vostra applicazione e ogni volta che il bambino scrive sul stdout (o legge da stdin, qualunque sia configurato) i dati viene scritto sul descrittore di file fornito invece.
Conchiglie utilizzano per implementare comandi con tubi, ad esempio /bin/ls | more
collegando lo stdout di un processo per la stdin dell'altro.
Altri suggerimenti
Lo scenario migliore per capire DUP e dup2 è reindirizzamento.
La prima cosa che dobbiamo sapere è che il sistema ha 3 ids di file di default (o variabili che indicano le fonti di uscita o di ingresso) che si occupa di ingresso e uscita. Sono stdin
, stdout
, stderr
, in interi sono 0
, 1
, 2
. La maggior parte delle funzioni come fprintf
o cout
sono direttamente uscita stdout
.
Se vogliamo reindirizzare l'output, un modo è dare, per esempio, fprintf
funzionano più argomenti che indicano in
e out
.
Tuttavia, c'è un modo più elegante: siamo in grado di sovrascrivere gli ID di file predefiniti per renderli punta al file che vogliamo ricevere l'output. dup
e dup2
esattamente lavorare in questa situazione.
Cominciamo con un semplice esempio ora: supponiamo di voler reindirizzare l'output di fprintf
in un file txt denominato "chinaisbetter.txt". Prima di tutto abbiamo bisogno di aprire questo file
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
Poi vogliamo stdout
per puntare a "chinaisbetter.txt" utilizzando la funzione DUP:
dup2(fw,1);
Ora stdout (1) indica il descrittore di "chinaisbetter.txt" anche se è ancora 1, ma l'output viene reindirizzato ora.
Quindi è possibile utilizzare printf
come normale, ma i risultati saranno nel file txt invece di mostrare direttamente sullo schermo:
printf("Are you kidding me? \n");
PS :
-
Questo dà solo una spiegazione intuitiva, può essere necessario controllare la pagina di manuale o di informazioni dettagliate. In realtà, noi diciamo "copia" qui, non stanno copiando tutto.
-
Il file id qui si riferisce al gestore del file. Il descrittore di file di cui sopra è una struct le informazioni del file di record.
Quando si è curiosi di sapere funzioni POSIX, specialmente quelli che sembrano per duplicare se stessi, è generalmente buona a selezionare la norma stessa . Al fondo di solito vedere esempi, così come il ragionamento dietro l'attuazione (e l'esistenza) di entrambi.
In questo caso:
Le sezioni che seguono sono informative.
Esempi
reindirizzare l'output standard di un file
Il seguente esempio chiude uscita standard per gli attuali processi, ri-assegna uscita standard per andare al file indicato da pfd
, e chiude il descrittore di file originale per ripulire.
#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
Reindirizzamento dei messaggi di errore
L'esempio seguente reindirizza i messaggi da stderr
a stdout
.
#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
Utilizzo Application
Nessuno.
Motivazioni
Le funzioni dup()
e dup2()
sono ridondanti. I loro servizi sono forniti anche dalla funzione fcntl()
. Sono stati inclusi in questo volume di IEEE Std 1003.1-2001 principalmente per ragioni storiche, dal momento che molte applicazioni esistenti li usano.
Mentre il segmento di codice breve mostrata è molto simile nel comportamento a dup2()
, un conforme attuazione basato su altre funzioni definite in questo volume di IEEE Std 1003.1-2001 è molto più complessa. Almeno evidente è il possibile effetto di una funzione segnale cattura che potrebbe essere invocata tra gradini e allocare o deallocare descrittori di file. Questo potrebbe essere evitato bloccando i segnali.
La funzione dup2()
non è contrassegnato obsolescenza perché presenta una versione dai tipi di funzionalità fornita in una versione tipo non sicuri fcntl()
. E 'utilizzato in associazione POSIX Ada.
La funzione dup2()
non è destinato all'uso in regioni critiche come un meccanismo di sincronizzazione.
Nella descrizione di [EBADF], il caso di fildes essendo fuori range è incluso caso proposta di fildes non essere valido. Le descrizioni per fildes
e fildes2
sono diversi perché l'unico tipo di invalidità che è rilevante per fildes2
è se è fuori portata; cioè, non importa se fildes2
fa riferimento a un file aperto quando la chiamata viene effettuata dup2()
.
Direzioni future
Nessuno.
Vedere anche
close()
, fcntl()
, open()
, il volume Base Definitions di IEEE Std 1003.1-2001, <unistd.h>
Cronologia delle modifiche
La prima volta nel Problema 1. Derivato dal numero 1 del SVID.
Un esempio pratico è il reindirizzamento messaggi di output a qualche altro flusso come un file di log. Ecco un codice di esempio per il reindirizzamento I / O.
Si prega di fare riferimento al post originale qui
#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()");
}
redirezione I / O nel guscio sarebbe molto probabilmente essere implementato utilizzando chiamate di sistema dup2 / fcnlt.
Si può facilmente emulare il tipo $program 2>&1 > logfile.log
di reindirizzamento usando la funzione dup2.
Il programma di seguito reindirizza sia stdout e stderr .i.e emula il comportamento del $program 2>&1 > output
utilizzando il 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