# FIFO Ένα FIFO - ένας *ονομασμένος σωλήνας* - είναι ένας σωλήνας με όνομα στο σύστημα αρχείων. Δύο προγράμματα που δεν μοιράζονται κανέναν γονέα, ξεκινημένα ανεξάρτητα από διαφορετικά κελύφη, μπορούν ωστόσο να επικοινωνήσουν: το ένα ανοίγει τη διαδρομή για εγγραφή, το άλλο την ανοίγει για ανάγνωση, και τα bytes ρέουν μεταξύ τους ακριβώς όπως μέσα από έναν ανώνυμο [`pipe`](../../p5/core/perlfunc/pipe.md). Η διαδρομή είναι ένα σημείο συνάντησης· κανένα δεδομένο δεν αποθηκεύεται ποτέ στο ίδιο το αρχείο. Αυτό είναι το κανάλι στο οποίο καταφεύγετε όταν οι διεργασίες είναι *μη σχετιζόμενες* - όταν ένα απλό `pipe` είναι αδύνατο επειδή δεν υπήρξε ποτέ ένα κοινό `fork` από το οποίο να κληρονομηθεί ο περιγραφέας. ## Δημιουργία του FIFO Ένα FIFO δημιουργείται μία φορά, ως ειδικό αρχείο, με την `POSIX::mkfifo`. Μετά από αυτό ανοίγεται όπως κάθε άλλη διαδρομή: ```perl use POSIX qw(mkfifo); my $path = "/tmp/demo.fifo"; mkfifo($path, 0600) or die "mkfifo $path: $!"; ``` Το δεύτερο όρισμα είναι ο τρόπος δικαιωμάτων, τα ίδια `0600` / `0644` που θα περνούσατε στην [`chmod`](../../p5/core/perlfunc/chmod.md) - αποφασίζει ποιος μπορεί να ανοίξει το FIFO. Η κλήση αποτυγχάνει αν η διαδρομή υπάρχει ήδη, οπότε μια μακρόχρονη αρχικοποίηση τυπικά κάνει πρώτα `unlink` ένα παλιό FIFO. ## Παραγωγός και καταναλωτής Η χαρακτηριστική συμπεριφορά ενός FIFO είναι ότι **η `open` μπλοκάρει μέχρι να είναι παρόντα και τα δύο άκρα**. Ένας αναγνώστης που ανοίγει τη διαδρομή περιμένει μέχρι κάποιος εγγραφέας να την ανοίξει επίσης, και αντιστρόφως. Αυτή η συνάντηση είναι το χαρακτηριστικό: συγχρονίζει δύο προγράμματα που ποτέ δεν συμφώνησαν ως προς τον χρονισμό. Αυτό το μοναδικό πρόγραμμα παρουσιάζει και τα δύο άκρα κάνοντας fork, αλλά τα δύο μισά θα λειτουργούσαν εξίσου καλά ως δύο ξεχωριστά scripts που εκτελούνται από δύο τερματικά: ```perl use POSIX qw(mkfifo); my $path = "/tmp/demo.fifo"; unlink $path; # clear any stale FIFO mkfifo($path, 0600) or die "mkfifo $path: $!"; my $kid = fork() // die "fork: $!"; if ($kid == 0) { # Producer: open for writing (blocks until a reader appears). open my $w, ">", $path or die "producer open: $!"; $w->autoflush(1); print $w "from-producer\n"; close $w; exit 0; } # Consumer: open for reading (blocks until a writer appears). open my $r, "<", $path or die "consumer open: $!"; my $line = <$r>; print "consumer read: $line"; # consumer read: from-producer close $r; waitpid($kid, 0); unlink $path; # remove the FIFO when finished ``` Οι δύο κλήσεις `open` είναι ο συγχρονισμός. Όποια διεργασία φτάσει πρώτη στην `open` της σταθμεύει εκεί μέχρι να φτάσει η άλλη· κατόπιν προχωρούν και οι δύο μαζί. Μόλις ανοίξουν, οι περιγραφείς ανάγνωσης και εγγραφής συμπεριφέρονται σαν τα δύο άκρα οποιουδήποτε σωλήνα - αναγνώσεις γραμμών, [`readline`](../../p5/core/perlfunc/readline.md), [`print`](../../p5/core/perlfunc/print.md) με ενταμιευτή, όλα αμετάβλητα. Δύο πρακτικές σημειώσεις: - **Αυτόματη εκκένωση στον εγγραφέα.** Όπως με κάθε σωλήνα και υποδοχή, μια εγγραφή με ενταμιευτή μπορεί να μην φτάσει ποτέ στον αναγνώστη μέχρι να γεμίσει ο ενταμιευτής ή να κλείσει ο περιγραφέας. Ορίστε `autoflush(1)` αν ο αναγνώστης περιμένει κάθε γραμμή τη στιγμή που παράγεται. - **Ένα FIFO παραμένει στον δίσκο.** Η `mkfifo` αφήνει πίσω της ένα ειδικό αρχείο που επιζεί και των δύο διεργασιών. Αφαιρέστε το με [`unlink`](../../p5/core/perlfunc/unlink.md) όταν τελειώσει η συνομιλία, με τον ίδιο τρόπο που θα καθαρίζατε ένα αρχείο κλειδώματος. ## Διασταυρούμενοι σύνδεσμοι αναφοράς - [`open`](../../p5/core/perlfunc/open.md) - ανοίγει τη διαδρομή του FIFO για ανάγνωση ή εγγραφή - [`pipe`](../../p5/core/perlfunc/pipe.md) - ο συγγενής ανώνυμου σωλήνα για σχετιζόμενες διεργασίες - [`unlink`](../../p5/core/perlfunc/unlink.md) - αφαιρεί το FIFO όταν τελειώσετε - [`readline`](../../p5/core/perlfunc/readline.md) - η συνάρτηση πίσω από το `<$fh>` ## Επόμενο Όταν δύο διεργασίες χρειάζονται μια σύνδεση αντί για μια μονόδρομη διαδρομή - αίτηση και απάντηση, και στις δύο κατευθύνσεις ταυτόχρονα - καταφύγετε σε μια υποδοχή. Δείτε [Υποδοχές UNIX-domain και UDP](sockets-unix-udp.md) και [Υποδοχές TCP](sockets-tcp.md).