# FIFOs FIFO - *named pipe* - הוא pipe בעל שם על מערכת הקבצים. שתי תכניות שאינן חולקות הורה, שהופעלו באופן עצמאי מ־shells שונים, עדיין יכולות לתקשר: האחת פותחת את הנתיב לכתיבה, השנייה פותחת אותו לקריאה, ובתים זורמים ביניהן בדיוק כמו דרך [`pipe`](../../p5/core/perlfunc/pipe.md) אנונימי. הנתיב הוא נקודת מפגש; שום מידע אינו נשמר אי־פעם בקובץ עצמו. זהו הערוץ שיש לפנות אליו כאשר התהליכים הם *בלתי־קשורים* - כאשר `pipe` רגיל אינו אפשרי משום שמעולם לא היה `fork` משותף שממנו ניתן לרשת את ה־descriptor. ## יצירת ה־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, אך שני החצאים היו עובדים באותה מידה כשני סקריפטים נפרדים המורצים משני טרמינלים: ```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` שלו חונה שם עד שהאחר מגיע; ואז שניהם ממשיכים יחד. לאחר הפתיחה, מטפלי הקריאה והכתיבה מתנהגים כמו שני הקצוות של כל pipe - קריאות שורה, [`readline`](../../p5/core/perlfunc/readline.md), [`print`](../../p5/core/perlfunc/print.md) עם buffering, הכל ללא שינוי. שתי הערות מעשיות: - **Autoflush בכותב.** כמו בכל pipe וסוקט, כתיבה עם buffering עלולה לעולם לא להגיע לקורא עד שה־buffer מתמלא או שהמטפל נסגר. הגדירו `autoflush(1)` אם הקורא מצפה לכל שורה ברגע שהיא מיוצרת. - **FIFO נשאר על הדיסק.** `mkfifo` משאיר אחריו קובץ מיוחד ששורד את שני התהליכים. הסירו אותו עם [`unlink`](../../p5/core/perlfunc/unlink.md) כאשר השיחה הסתיימה, באותו אופן שבו הייתם מנקים קובץ נעילה. ## קישורים מקושרים להפניה - [`open`](../../p5/core/perlfunc/open.md) - פתיחת נתיב ה־FIFO לקריאה או לכתיבה - [`pipe`](../../p5/core/perlfunc/pipe.md) - מקבילת ה־pipe האנונימי לתהליכים קשורים - [`unlink`](../../p5/core/perlfunc/unlink.md) - הסרת ה־FIFO בסיום - [`readline`](../../p5/core/perlfunc/readline.md) - הפונקציה שמאחורי `<$fh>` ## הבא כאשר שני תהליכים צריכים חיבור במקום נתיב חד־כיווני - בקשה ותגובה, שני הכיוונים בבת אחת - פנו לסוקט. ראו [סוקטים בתחום UNIX ו־UDP](sockets-unix-udp.md) ו־[סוקטי TCP](sockets-tcp.md).