dup2 / dup - perché dovrei duplicare un descrittore di file?


85

Sto cercando di capire l'uso di dup2e dup.

Dalla pagina man:

Perché dovrei aver bisogno di quella chiamata di sistema? a che serve duplicare il descrittore di file?

Se ho il descrittore di file, perché dovrei farne una copia?

Apprezzerei se potessi spiegarmi e darmi un esempio in cui dup2/ dupè necessario.

Grazie


Come implementereste la funzionalità di piping delle shell senza dupo dup2? È necessario chiamare pipe(2)e poi di avere uno dei descrittori di file dup-ED per esempioSTDIN_FILENO
Basile Starynkevitch

1
Possibile duplicato di esempi pratici usa dup o dup2
DrTyrsa

Risposte:


48

La chiamata di sistema dup duplica un descrittore di file esistente, restituendone uno nuovo che fa riferimento allo stesso oggetto I / O sottostante.

Dup consente alle shell di implementare comandi come questo:

2> & 1 dice alla shell di dare al comando un descrittore di file 2 che è un duplicato del descrittore 1. (cioè stderr e stdout puntano allo stesso fd).
Ora il messaggio di errore per la chiamata di ls su file non esistenti e l'output corretto di ls su file esistente vengono visualizzati nel file tmp1 .

Il codice di esempio seguente esegue il programma wc con lo standard input connesso all'estremità di lettura di una pipe.

Il figlio duplica la fine della lettura sul descrittore di file 0, chiude il file de scriptors in p ed esegue wc. Quando wc legge dal suo standard input, legge dal pipe.
Questo è il modo in cui i tubi vengono implementati usando dup, beh, un uso di dup ora usi pipe per costruire qualcos'altro, questa è la bellezza delle chiamate di sistema, costruisci una cosa dopo l'altra usando strumenti che sono già lì, questi strumenti sono stati costruiti a turno usando qualcos'altro e così via .. Alla fine le chiamate di sistema sono gli strumenti più basilari che si ottengono nel kernel

Saluti :)


1
Quindi dupè utile per il chiamante e non per il lsprogramma stesso? C'è qualche vantaggio nell'aver duputilizzato un programma come ls stesso se ha già accesso al file? Qui, ad esempio, lsscrive errori in 2cui è hardcoded, quindi ho un modo per sovrascriverlo come consumatore di ls. Penso che questo sia un punto sottile, no?
Nishant

3
Il tuo programma di esempio sembra avere un bug; stai chiamando dup(p[STDIN])ma poi butti via il risultato. Volevi usare dup2(p[STDIN], 0)?
Quuxplusone

1
@Quuxplusone duprestituisce il "descrittore con il numero più basso attualmente non utilizzato dal processo". Poiché fd 0 è stato appena chiuso, dupdovrebbe restituire 0. dup2è esplicito su quale fd dovrebbe essere usato, invece di usare solo il più basso fd libero, quindi lo preferirei.
Wodin

@ Wodin: Ah, scommetto che hai ragione su quello che stava pensando OP. Ho anche ragione, però, che "appena chiuso" è relativo e il codice di OP potrebbe interrompersi in presenza, ad esempio, di thread simultanei che potrebbero aprire anche file?
Quuxplusone

@Quuxplusone Sospetto che tu abbia ragione, ma non lo so per certo. Ma in quel caso avrai altri problemi. Se chiudi stdin perché vuoi leggere da qualche altra parte e poi un altro thread apre un file prima di te, otterrà fd 0. Se poi usi dup2, chiuderà l'fd che l'altro thread ha aperto, quindi l'altro thread ora leggerà (e scriverà su?) il file che apri. Comunque, se ricordo bene non dovresti chiamare exec*da un processo multithread. Ma non sono un esperto di threading :)
Wodin

18

Un altro motivo per duplicare un descrittore di file è usarlo con fdopen. fclosechiude il descrittore di file a cui è stato passato fdopen, quindi se non vuoi che il descrittore di file originale venga chiuso, devi dupprima duplicarlo con .


fdopen()sembra non duplicare un descrittore di file, crea solo un buffer nello spazio utente.
user218867

3
Hai letto male la mia risposta. Il punto è che potresti volere dupil fd prima di passarlo a fdopenpoiché fcloselo chiuderà.
R .. GitHub STOP HELPING ICE

1
@ theferrit32: se si alloca un FILEhandle per accedere a un file aperto preesistente tramite le interfacce stdio, è necessario chiamare fcloseper deallocare quell'handle FILE. Se vuoi continuare a utilizzare il file aperto sottostante, o se l'architettura del tuo softwareè tale che il codice "proprietario" originale per il descrittore di file saràclose lo , il fatto che fclosechiuda anche il descrittore di file sottostante a cui è stato consegnato fdopenè un problema. È possibile evitare questo problema utilizzando dupper creare un nuovo descrittore di file a cui passare lo stesso file aperto fdopen, in modo che fclosenon chiuda quello originale.
R .. GitHub STOP AIUTO IL GHIACCIO

1
Il punto è che fdopen () sposta la proprietà di fd su FILE, invece di copiarlo . Questo è qualcosa di cui gli utenti dovrebbero essere consapevoli. I consumatori che devono mantenere un fdhandle utilizzabile oltre FILEall'oggetto devono duplicare il file fd. È tutto.
Conrad Meyer

1
@ConradMeyer: Sì, è un ottimo modo per spiegarlo, con una nota che non c'è alcuna operazione per "spostare la proprietà" da FILEuna volta trasferita la proprietà ad essa.
R .. GitHub SMETTA DI AIUTARE ICE

4

dup viene utilizzato per poter reindirizzare l'output da un processo.

Ad esempio, se si desidera salvare l'output da un processo, si duplica l'output (fd = 1), si reindirizza l'fd duplicato in un file, quindi si esegue il fork ed si esegue il processo e, quando il processo finisce, si reindirizza nuovamente il salvato fd in output.


4

Alcuni punti relativi a dup / dup2 possono essere annotati per favore

dup / dup2 - Tecnicamente lo scopo è condividere una voce della tabella file all'interno di un singolo processo da diversi handle. (Se si esegue il fork, il descrittore viene duplicato per impostazione predefinita nel processo figlio e anche la voce della tabella dei file è condivisa).

Ciò significa che possiamo avere più di un descrittore di file con attributi possibilmente diversi per una singola voce di tabella di file aperti utilizzando la funzione dup / dup2.

(Anche se attualmente sembra che solo il flag FD_CLOEXEC sia l'unico attributo per un descrittore di file).

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

Le differenze sono (per l'ultimo) - A parte qualche valore errno tra dup2 e fcntl close seguito da fcntl possono aumentare le condizioni di gara poiché sono coinvolte due chiamate di funzione.

I dettagli possono essere verificati da http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

Un esempio di utilizzo -

Un esempio interessante durante l'implementazione del controllo del lavoro in una shell, dove è possibile vedere l'uso di dup / dup2 .. nel link sottostante

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.