questo può essere fatto in circa tre fasi:
- Cancella il close-on-exec bandiera sul descrittore di file.
- Comunicare al programma exec quale programma di descrizione del file utilizzare.
- Ripristina il descrittore di file in un handle.
1. Perl (per impostazione predefinita) imposta il flag close-on-exec su descrittori di file si apre. Ciò significa che i descrittori di file non verranno conservati attraverso uno exec
. È necessario cancellare questo flag prima:
use Fcntl;
my $flags = fcntl $fh, F_GETFD, 0 or die "fcntl F_GETFD: $!";
fcntl $fh, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!";
2. Ora che il descrittore di file rimarrà aperto tutta exec
, è necessario indicare al programma che DESCRIPTOR è:
my $fd = fileno $fh;
exec 'that_program', $fd; # pass it on the command line
# (you could also pass it via %ENV or whatever)
3 . Recuperare il filehandle dall'altra parte:
my $fd = $ARGV[0]; # or however you passed it
open my $fh, '+<&=', $fd; # fdopen
$fh->autoflush(1); # because "normal" sockets have that enabled by default
Ora avete un a maniglia di livello 1 in $fh
di nuovo.
Addendum: Come Ikegami menzionato in un commento, si può anche fare che la presa sta usando uno dei tre descrittori di file "standard" (0 (standard input), 1 (stdout), 2 (stderr)), che sono 1. lasciati aperti di default su execs, 2. hanno numeri conosciuti quindi non c'è bisogno di passare nulla, e 3. perl creerà automaticamente maniglie corrispondenti per loro.
open STDIN, '+<&', $fh; # now STDIN refers to the socket
exec 'that_program';
Ora that_program
può semplicemente utilizzare STDIN
. Funziona anche per l'output; non esiste alcuna restrizione inerente ai descrittori di file 0, 1, 2 che siano solo per input o output. È solo una convenzione che segue tutti i programmi Unix.
Sto per provare la procedura, ma ho una domanda sull'utilizzo di STDIN: può essere associato a una connessione bidirezionale come un socket? Tendo a pensare a fds 0-2 come semi-magico (specializzato in qualche modo per l'I/O del terminale). Sono davvero speciali se non nei modi che hai menzionato nel tuo addendum? – Chap
Il problema che sto riscontrando con la soluzione riguarda l'apertura dell'FD sia per l'input che per l'output. 'apri my $ fh, '<& =', $ fd;' lo apre per l'input.Ho provato a seguirlo con 'open $ fh, '> & =', $ fd;' ma ottiene l'errore: Bad file descriptor. (L'apertura precedente per l'input funziona.) Non riesco a trovare alcuna informazione su come aprire sia per l'input che per l'output. – Chap
Un altro followup: l'open (per i/o bidirezionale) avrebbe dovuto essere 'open $ fh, '+> & =', $ fd;'. Inoltre, avevo bisogno di pubblicare '$ fh-> autoflush (1)'. – Chap