שיעור 6: fork() — יצירת תהליך ילד
fork() הוא ה-syscall שמגדיל פי שניים את מספר התהליכים: הוא יוצר העתק מדויק של התהליך הנוכחי. הבנת fork() חיונית לכל מהנדס מערכות — nvidia-docker ו-Slurm GPU allocator משתמשים בו ליצירת סביבות מבודדות לכל job GPU. כשמשהו לא עובד עם תהליכי GPU, הידע על fork() הוא כלי האבחון הראשון.
fork() הוא כמו לצלם עותק של כל תוכן המח שלך ולהכניס אותו לגוף אחר — פתאום יש שני אנשים שזכור להם הכל עד לרגע הצילום. ההבדל היחיד הוא שלאחד יש מספר ID שונה מהשני.
- fork()
- syscall שיוצר תהליך ילד שהוא העתק של תהליך האב. fork() מחזיר 0 לילד, ה-PID של הילד לאב, ו--1 אם נכשל.
- Copy-on-Write (COW)
- אופטימיזציה של fork(): הקרנל לא מעתיק פיזית את כל הזיכרון מיד. דפי זיכרון משותפים עם האב עד שאחד מהם כותב — ואז רק אותו דף מועתק.
- תהליך ילד
- תהליך שנוצר על ידי fork(). הילד מקבל PID חדש, אבל PPID שלו הוא ה-PID של האב. לילד יש העתק עצמאי של מרחב הזיכרון.
- getpid() / getppid()
- syscalls שמחזירים את ה-PID של התהליך הנוכחי ואת ה-PID של האב שלו בהתאמה. שימושיים לאחרי fork() להבחין מי אב ומי ילד.
- שכפול מרחב כתובות
- fork() יוצר לילד מרחב כתובות וירטואלי עצמאי עם אותן כתובות כמו האב. שינוי של משתנה בילד לא ישפיע על האב ולהיפך (בזכות Copy-on-Write).