לדלג לתוכן

מיפוי זיכרון מוסבר - איך קובץ שלם הופך למערך בזיכרון בלי לקרוא אותו

הדרך "הרגילה" לגשת לתוכן קובץ היא לקרוא אותו, בית אחר בית או בבלוקים, באמצעות read. אבל יש דרך אחרת, יעילה בהרבה במקרים מסוימים - למפות את הקובץ ישירות לתוך מרחב הזיכרון של התהליך, ולגשת אליו כאילו הוא סתם מערך רגיל בזיכרון. המנגנון הזה נקרא מיפוי זיכרון - memory mapping, והוא אחד הכלים החזקים ביותר שהקרנל נותן לתוכניות.

אז מה זה בעצם מיפוי זיכרון

הקריאה למערכת שמבצעת את זה נקראת mmap. במקום להעתיק תוכן של קובץ מהדיסק לבאפר בזיכרון בתהליך הדרגתי, mmap פשוט מחבר טווח כתובות במרחב הזיכרון הווירטואלי של התהליך, לתוכן של הקובץ. מהרגע הזה, כל גישה לזיכרון בטווח הזה, קריאה או כתיבה, מטופלת אוטומטית על ידי הקרנל כגישה לקובץ, בלי שהתוכנית צריכה לקרוא לפונקציות read או write בכלל.

זה נשמע כמעט קסום, אבל זה עובד בזכות אותו מנגנון שכבר פגשנו כשדיברנו על טעינת תהליכים - זיכרון וירטואלי ו-demand paging. הקרנל לא טוען את כל הקובץ לזיכרון פיזי מיד. הוא רק יוצר את המיפוי, ורק כשהתוכנית באמת ניגשת לחלק מסוים של הקובץ, מתרחשת טעינה בפועל של אותו עמוד זיכרון ספציפי, לא יותר.

למה זה מהיר יותר מקריאה רגילה

קריאת קובץ עם read דורשת בדרך כלל שני עותקים של הנתונים - אחד בתוך הקרנל, ואחד שמועתק משם לבאפר של התוכנית. עם mmap, אין העתקה כפולה כזאת - הזיכרון של התהליך פשוט "רואה" את אותם עמודי זיכרון שדרכם הקרנל ניגש לקובץ, בלי שכבת העתקה נוספת באמצע.

זה יתרון משמעותי כשעובדים עם קבצים גדולים, כי אפשר לגשת לחלקים ספציפיים מהקובץ, בלי לטעון את כולו לזיכרון מראש, ובלי לנהל ידנית קריאה שלב אחר שלב. בסיסי נתונים גדולים ומנועי חיפוש משתמשים בטכניקה הזאת בדיוק בשביל זה - לתת למערכת ההפעלה לנהל את הזיכרון בצורה חכמה, במקום לממש את זה ידנית בתוך התוכנית.

מיפוי משותף מול מיפוי פרטי

יש שני סוגים עיקריים של מיפוי, וההבדל ביניהם קריטי. מיפוי משותף - shared mapping, אומר ששינויים שתעשו בזיכרון הממופה יזלגו בחזרה לקובץ עצמו על הדיסק, וגם יהיו גלויים לתהליכים אחרים שמיפו את אותו קובץ. זו למעשה דרך נוספת לתקשורת בין תהליכים - כמה תהליכים יכולים לשתף אותו אזור זיכרון ולתקשר דרכו ישירות, בלי צינורות ובלי קריאות מערכת נוספות.

מיפוי פרטי - private mapping, לעומת זאת, נותן לכל תהליך עותק וירטואלי משלו. שינויים שהתהליך עושה נשארים אצלו בלבד, ולא משפיעים על הקובץ המקורי ולא על תהליכים אחרים - טכניקה שנקראת copy-on-write, שבה עותק אמיתי נוצר רק ברגע שבאמת כותבים לזיכרון, לא לפני כן.

מיפוי אנונימי - זיכרון בלי קובץ בכלל

mmap לא חייב להיות קשור לקובץ קיים. אפשר לבקש ממנו מיפוי אנונימי - anonymous mapping, שפשוט מקצה בלוק זיכרון ריק, בלי שום קשר לדיסק. זו בדיוק הדרך שבה מקצי זיכרון כמו malloc מבקשים מהקרנל בלוקים גדולים של זיכרון בפועל, מאחורי הקלעים, לפני שהם מנהלים את החלוקה הפנימית שלו בעצמם.

למה כדאי להכיר את זה

מיפוי זיכרון הוא אחד הכלים שמראים הכי טוב איך זיכרון וירטואלי הופך יכולות שנשמעות מסובכות לפעולה פשוטה - קובץ ענק על הדיסק הופך למערך רגיל שגישה אליו עולה כמו גישה לזיכרון, בלי צורך בניהול ידני מסורבל. הבנה של המנגנון הזה חשובה גם לביצועים, וגם להבנה איך תהליכים חולקים ספריות משותפות וזיכרון ביניהם בפועל.

זה בדיוק סוג ההבנה שאנחנו בונים בקורס ליבת המחשב - איך זיכרון וירטואלי, קבצים, ותהליכים נפגשים במקום אחד.

ואם mmap נשמע לכם עדיין קצת מופשט, יש קהילה שכבר עברה את השלב הזה.

הצטרפו לקהילה בדיסקורד

לסיכום

מיפוי זיכרון מחבר בין קובץ לבין מרחב הזיכרון של תהליך, כך שגישה לקובץ נראית בדיוק כמו גישה למערך רגיל בזיכרון. הוא חוסך העתקות מיותרות, מאפשר לכמה תהליכים לשתף זיכרון בפועל, ומשמש גם בלי קובץ בכלל בתור הבסיס להקצאת זיכרון דינמית. ברגע שרואים אותו כהרחבה טבעית של זיכרון וירטואלי, קל הרבה יותר להבין למה הוא כלי כל כך מרכזי בכל מערכת שמתמודדת עם נתונים גדולים.