Można to zrobić w około trzy etapy:
- Opróżnij close-on-exec flagą na deskryptorze pliku.
- Powiedz programowi exec'd, który deskryptor pliku ma użyć.
- Przywróć deskryptor pliku do uchwytu.
1. Perl (domyślnie) ustawia flagę close-on-exec deskryptorów otwiera. Oznacza to, że deskryptory plików nie będą zachowane w postaci exec
. Trzeba usunąć tę flagę pierwszy:
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. Teraz, gdy deskryptor pliku pozostanie otwarte w poprzek exec
, trzeba powiedzieć, że program, który jest deskryptor:
my $fd = fileno $fh;
exec 'that_program', $fd; # pass it on the command line
# (you could also pass it via %ENV or whatever)
3 . Odzyskaj uchwytu pliku z drugiej strony:
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
teraz masz Per Uchwyt na poziomie L ponownie w $fh
.
Uzupełnienie: Jak Ikegami wspomniano w komentarzu, można również upewnić się, że gniazdo jest za pomocą jednego z trzech "standardowych" deskryptorów (0 (stdin), 1 (stdout), 2 (stderr)), który są 1. domyślnie otwarte dla wszystkich execów, 2. mają znane liczby, więc nie trzeba niczego przekazywać, a 3. perl automatycznie tworzy odpowiednie dla nich uchwyty.
open STDIN, '+<&', $fh; # now STDIN refers to the socket
exec 'that_program';
that_program
Teraz można po prostu użyć STDIN
. Działa to nawet dla wyjścia; nie ma nieodłącznych ograniczeń dla deskryptorów plików 0, 1, 2, że są one przeznaczone tylko do wejścia lub wyjścia. To tylko konwencja, którą podążają wszystkie programy unix.
Mam zamiar wypróbować twoją procedurę, ale mam pytanie dotyczące używania STDIN: czy może być związany z dwukierunkowym połączeniem, takim jak gniazdo? Zwykle uważam, że fds 0-2 jest pół-magiczny (wyspecjalizowany w jakiś sposób w terminalowym we/wy). Czy są one naprawdę wyjątkowe, poza tymi, o których wspomniałeś w swoim addendum? – Chap
Problem, który mam z twoim rozwiązaniem, ma związek z otwarciem FD dla wejścia i wyjścia. 'otwórz moje $ fh, <& = ', $ fd;' po prostu otwiera je dla danych wejściowych.Próbowałem to zrobić z 'open $ fh,>> & = ', $ fd;', ale pojawia się błąd: Zły deskryptor pliku. (Poprzedni otwiera dla wejścia działa.) Nie mogę znaleźć żadnych informacji o tym, jak otworzyć dla wejścia i wyjścia. – Chap
Kolejna obserwacja: otwarta (dla dwukierunkowego wejścia/wyjścia) powinna mieć postać 'otwórz $ fh, '+> & =', $ fd;'. Musiałem również wydać '$ fh-> autoflush (1)'. – Chap