waitpid#
Περιμένει να τερματίσει συγκεκριμένη διεργασία-παιδί και τη συλλέγει.
Η waitpid είναι το στοχευμένο αντίστοιχο της wait. Ενώ η wait συλλέγει οποιοδήποτε παιδί και μπλοκάρει μέχρι ένα να εξέλθει, η waitpid σας επιτρέπει να ονομάσετε ποιο παιδί (ή ποια ομάδα παιδιών) να περιμένετε, και σας επιτρέπει να δημοσκοπείτε αντί να μπλοκάρετε, περνώντας WNOHANG στα FLAGS. Η κατάσταση εξόδου του παιδιού που συλλέχθηκε προσγειώνεται στην $?, όπως ακριβώς και με την wait.
Σύνοψη#
use POSIX ":sys_wait_h";
waitpid $pid, 0; # block until $pid exits
waitpid $pid, WNOHANG; # poll: is $pid done yet?
waitpid -1, WNOHANG; # reap any ready zombie, don't block
Τι επιστρέφεται#
Το PID του παιδιού που συλλέχθηκε σε επιτυχία.
0όταν είναι ορισμένο τοWNOHANGκαι υπάρχει τουλάχιστον ένα παιδί που ταιριάζει αλλά κανένα δεν έχει τερματίσει ακόμη - δηλαδή «τρέχει ακόμη, δοκιμάστε αργότερα».-1όταν καμία διεργασία-παιδί δεν ταιριάζει με τοPID(δεν υπήρξε ποτέ, έχει ήδη συλλεχθεί, ή - σε συστήματα που κάνουν αυτόματη συλλογή - συγκομίστηκε από τον πυρήνα χωρίς τη βοήθεια της Perl).
Η κατάσταση εξόδου του παιδιού γράφεται στην $? και η ωμή OS-native κατάσταση στην ${^CHILD_ERROR_NATIVE} σε κάθε επιτυχημένη συλλογή. Αποκωδικοποιήστε την $? με τον ίδιο τρόπο όπως μετά από wait ή κλήση με backticks:
my $reaped = waitpid $pid, 0;
if ($reaped > 0) {
my $exit = $? >> 8;
my $signal = $? & 127;
my $core = $? & 128;
}
Τι σημαίνει το PID#
Το PID επιλέγει ποια παιδιά είναι πρόθυμη να συλλέξει η waitpid:
Θετικό PID - περιμένει για το συγκεκριμένο παιδί. Επιστροφή
-1σημαίνει ότι δεν υπάρχει τέτοιο παιδί (το έχετε ήδη συλλέξει, ή δεν ήταν ποτέ δικό σας).0- περιμένει για οποιοδήποτε παιδί στην τρέχουσα ομάδα διεργασιών. Χρήσιμο όταν το πρόγραμμά σας έχει ενταχθεί σε ομάδα διεργασιών με άλλες συνεργαζόμενες διεργασίες και θέλετε να συγκομίζετε μόνο τα δικά σας.-1- περιμένει για οποιοδήποτε παιδί, ίδια εμβέλεια με τηνwait.Μικρότερο από
-1- περιμένει για οποιοδήποτε παιδί του οποίου το ID ομάδας διεργασιών ισούται με την απόλυτη τιμή τουPID. Ηwaitpid -$pgid, 0περιμένει για οποιοδήποτε μέλος της ομάδας διεργασιών$pgid.
Τα FLAGS είναι bitmask. Η φορητή σημαία είναι το WNOHANG, που κάνει την κλήση μη μπλοκαριστική: αν κανένα παιδί που ταιριάζει δεν έχει εξέλθει, η waitpid επιστρέφει 0 αμέσως αντί να κοιμηθεί. FLAGS ίσο με 0 σημαίνει «μπλόκαρε μέχρι κάτι να είναι συλλέξιμο», και υλοποιείται σε κάθε πλατφόρμα όπου τρέχει η Perl - ακόμη και σε αυτές χωρίς εγγενή κλήση συστήματος waitpid(2), όπου η Perl την εξομοιώνει θυμούμενη τις καταστάσεις εξόδου παιδιών που έχει ήδη δει.
Καθολική κατάσταση που επηρεάζει#
$?- τίθεται στην κατάσταση εξόδου του παιδιού που συλλέχθηκε (μετατοπισμένη: το υψηλό byte = κωδικόςexit, τα χαμηλά 7 bits = σήμα, το bit0x80= σημαία core-dumped).${^CHILD_ERROR_NATIVE}- τίθεται στην ωμή OS-native λέξη κατάστασης, πριν η Perl την κανονικοποιήσει σε$?.
Καμία από τις δύο μεταβλητές δεν αγγίζεται όταν η waitpid επιστρέφει 0 (WNOHANG και τίποτα έτοιμο) ή -1 (κανένα παιδί που να ταιριάζει).
Παραδείγματα#
Μπλοκάρισμα μέχρι γνωστό παιδί να τελειώσει, και κατόπιν επιθεώρηση του κωδικού εξόδου του:
my $pid = fork // die "fork: $!";
if ($pid == 0) {
exec "/usr/bin/gzip", "big.log" or die "exec: $!";
}
waitpid $pid, 0;
die "gzip failed with status ", $? >> 8 if $?;
Δημοσκόπηση χωρίς μπλοκάρισμα - χρήσιμη μέσα σε βρόχο γεγονότων ή χειριστή SIGCHLD:
use POSIX ":sys_wait_h";
sub harvest_children {
while ((my $kid = waitpid -1, WNOHANG) > 0) {
warn "child $kid exited with ", $? >> 8, "\n";
}
}
Το κλασικό ιδίωμα «συλλογή κάθε εκκρεμούς zombie, χωρίς μπλοκάρισμα»:
use POSIX ":sys_wait_h";
1 while waitpid(-1, WNOHANG) > 0;
Αναμονή μόνο για παιδιά σε συγκεκριμένη ομάδα διεργασιών. Πρώτα setpgid, και κατόπιν στοχεύστε την ομάδα κάνοντας αρνητικό το ID της:
my $leader = fork // die "fork: $!";
if ($leader == 0) {
setpgid 0, 0; # become process-group leader
exec @worker_cmd or die "exec: $!";
}
setpgid $leader, $leader; # parent matches, races with child
# ... later, reap any member of that group:
while ((my $kid = waitpid -$leader, WNOHANG) > 0) {
log_exit($kid, $?);
}
Διάκριση των τριών τιμών επιστροφής σε ένα σημείο:
my $r = waitpid $pid, WNOHANG;
if ($r == $pid) { finalize_child($pid, $?) }
elsif ($r == 0) { still_running($pid) }
elsif ($r == -1) { warn "no such child $pid (already reaped?)" }
Οριακές περιπτώσεις#
Το
WNOHANGαπαιτείuse POSIX. Η σταθερά δεν είναι ενσωματωμένη στην Perl· προέρχεται από το άρθρωμαPOSIX, τυπικά μέσωuse POSIX ":sys_wait_h";. Το να γράφετε γυμνό ακέραιο (waitpid $pid, 1) λειτουργεί στο Linux αλλά δεν είναι φορητό και αποκρύπτει την πρόθεση.Το
$SIG{CHLD} = 'IGNORE'μπαίνει σε race με τηνwaitpid. Όταν λέτε στον πυρήνα να συλλέγει αυτόματα τα παιδιά, δεν μένει τίποτα για να βρει ηwaitpid- επιστρέφει-1με την$!ορισμένη σεECHILD. Επιλέξτε μία στρατηγική συλλογής ανά πρόγραμμα, όχι και τις δύο.PIDs που έχουν ήδη συλλεχθεί επιστρέφουν
-1. Το PID μεμονωμένου παιδιού μπορεί να συλλεχθεί μόνο μία φορά· μετά από αυτό ξεχνιέται. Αν δώσετε το ίδιο PID στηνwaitpidδύο φορές, η δεύτερη κλήση επιστρέφει-1.Το αρνητικό
PIDείναι ομάδα διεργασιών, όχι «οποιοδήποτε εκτός από αυτό». Ηwaitpid -1234, 0περιμένει για μέλη της ομάδας διεργασιών1234, όχι «κάθε παιδί εκτός από το PID 1234». Αναγνώστες ανεξοικείωτοι με τη σύμβαση POSIX συχνά το παρερμηνεύουν.Η
WNOHANGμεPID = -1είναι η πρότυπη μορφή «αποστράγγιση της ουράς zombies». Σε συνδυασμό με βρόχοwhileσυλλέγει κάθε παιδί που έχει ήδη εξέλθει και σταματά μόλις ο πυρήνας δεν έχει τίποτα άλλο να δώσει πίσω.Η τιμή επιστροφής
-1μπορεί επίσης να σημαίνει αυτόματη συλλογή. Σε συστήματα διαμορφωμένα να συλλέγουν αυτόματα τα παιδιά (π.χ. χειριστής$SIG{CHLD} = 'IGNORE'εγκατεστημένος στην έναρξη), ηwaitpidδεν βλέπει κανένα παιδί και επιστρέφει-1ακόμη και για PID που μόλις κάνατε fork. Δείτε τοperlipcγια τις σημειώσεις πλατφόρμας.Η μπλοκαριστική αναμονή είναι πάντα διαθέσιμη. Ακόμη και σε πλατφόρμες χωρίς εγγενή κλήση συστήματος
waitpid(2)ήwait4(2), ηwaitpid PID, 0λειτουργεί - η Perl την εξομοιώνει διατηρώντας τις καταστάσεις παιδιών που έχει ήδη συλλέξει.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
wait- μπλοκάρει για οποιοδήποτε παιδί· ισοδύναμη μεwaitpid -1, 0σε συστήματα που την υποστηρίζουνfork- δημιουργεί τα παιδιά που αργότερα θα συλλέξετε μεwaitpidkill- στέλνει σήμα στα ίδια PIDs και ομάδες διεργασιών που δέχεται ηwaitpid$?- κατάσταση εξόδου του παιδιού που συλλέχθηκε· αποκωδικοποιήστε ως$? >> 8για τον κωδικό εξόδου,$? & 127για το σήμα${^CHILD_ERROR_NATIVE}- ωμή OS-native λέξη κατάστασης για το ίδιο παιδίPOSIX- πηγή τουWNOHANGκαι του υπόλοιπου:sys_wait_h