לדלג לתוכן

6.5 מערכת הקבצים הוירטואלית פתרון

פתרונות - מערכת הקבצים הוירטואלית - VFS

פתרון 1 - בחינת inodes עם stat

א. מספרי ה-inode ישתנו בין מערכות. דוגמה:

/etc/passwd    - Inode: 131073
/etc/hostname  - Inode: 131098
/bin/ls        - Inode: 262145

ב. הפקודה stat מציגה מידע שלא מופיע ב-ls -l:
- מספר ה-inode
- מספר ההתקן (Device)
- מספר הקישורים הקשיחים (Links)
- גודל הבלוקים שהקובץ תופס בדיסק (Blocks)
- שלושה חותמות זמן מפורטות: Access (atime), Modify (mtime), Change (ctime). הפקודה ls -l מראה רק את mtime.
- סוג הקובץ (regular file, directory, symbolic link, וכו')

ג. הפקודה ls -i מראה רק את מספר ה-inode ושם הקובץ, בלי כל המידע הנוסף ש-stat מציג. זו דרך מהירה לראות את מספר ה-inode.


פתרון 2 - קישורים קשיחים מול קישורים רכים

א. מספר ה-inode של original.txt ו-hardlink.txt זהה! למשל:

1234567 -rw-r--r-- 2 user user 6 ... /tmp/original.txt
1234567 -rw-r--r-- 2 user user 6 ... /tmp/hardlink.txt

שימו לב גם שמספר הקישורים (הספרה 2 אחרי ההרשאות) עלה ל-2. שני ה-dentries מצביעים על אותו inode.

ב. מספר ה-inode של softlink.txt שונה מ-original:

1234999 lrwxrwxrwx 1 user user 18 ... /tmp/softlink.txt -> /tmp/original.txt

קישור רך הוא inode נפרד שהתוכן שלו הוא הנתיב של הקובץ המקורי.

ג. אחרי מחיקת original.txt:

  • hardlink.txt - עדיין עובד. אפשר לקרוא ממנו בלי בעיה. מחיקת original.txt פשוט הסירה dentry אחד מהinode. ה-inode עצמו (ותוכן הקובץ) עדיין קיים כי יש עוד dentry שמצביע עליו (hardlink.txt). מונה הקישורים ירד מ-2 ל-1. ה-inode וטבוך הקובץ ימחקו רק כשמונה הקישורים יגיע ל-0.

  • softlink.txt - לא עובד. מקבלים שגיאה: No such file or directory. ה-softlink מכיל את הנתיב /tmp/original.txt כטקסט. כשמנסים לפתוח אותו, הקרנל מנסה לפתור את הנתיב הזה, מגלה שאין dentry בשם original.txt בתיקיית /tmp, ונכשל. זה מה שנקרא "dangling symlink" - קישור רך שמצביע לקובץ שלא קיים.


פתרון 3 - חקירת נקודות mount

א. דוגמה טיפוסית:

  • / - בדרך כלל ext4 או xfs על מערכת רגילה, overlay על Docker container.
  • /proc - כן, מותקן. סוג מערכת הקבצים: proc. זו מערכת קבצים וירטואלית שהקרנל מספק.
  • /sys - כן, מותקן. סוג מערכת הקבצים: sysfs.
  • /tmp - תלוי בהפצה. בהפצות מסוימות (כמו Fedora, Arch) הוא מותקן כ-tmpfs (מערכת קבצים בRAM). בהפצות אחרות (כמו Ubuntu ישן יותר) הוא חלק ממערכת הקבצים של השורש.

ב. מערכות קבצים שמסומנות ב-nodev הן מערכות קבצים שלא צריכות התקן בלוק (block device) כדי לעבוד. דוגמאות: proc, sysfs, tmpfs, cgroup. הן וירטואליות - התוכן שלהן נמצא בזכרון בלבד.

מערכות קבצים ללא nodev צריכות התקן בלוק - הן מנהלות נתונים על דיסק. דוגמאות: ext4, xfs, btrfs, vfat.


פתרון 4 - page cache בפעולה

א. ערכים לדוגמה לפני קריאת הקובץ:

MemFree:  4096000 kB
Buffers:    32000 kB
Cached:   2048000 kB

ב. אחרי הרצת cat /usr/bin/python3 > /dev/null, הערכים ישתנו:

MemFree:  4092000 kB  (ירד קצת)
Buffers:    32000 kB  (לא השתנה)
Cached:   2052000 kB  (עלה בגודל הקובץ בערך)

ג. Cached גדל כי הקרנל שמר את תוכן הקובץ שקראנו ב-page cache. כשcat קרא את הקובץ, הקרנל טען את הדפים מהדיסק לRAM. גם אחרי שcat סיים, הדפים נשארו ב-cache.

ד. אם נקרא את אותו קובץ שוב, הוא לא ייקרא מהדיסק. הוא כבר ב-page cache! הread של VFS יבדוק את ה-page cache, ימצא את הדפים שם, ויעתיק מהRAM ישירות לbuffer של התהליך. זה הרבה יותר מהיר מקריאה מדיסק (מיקרו-שניות מול מילי-שניות).


פתרון 5 - שאלה תיאורטית

הזרימה של open("/home/user/notes.txt", O_RDONLY):

1. כניסה לקרנל - ה-syscall open נקלט. הקרנל מתחיל את תהליך פתרון הנתיב.

2. פתרון "/" (root) - הקרנל מתחיל מ-root dentry של התהליך (בדרך כלל השורש של מערכת הקבצים). הוא לוקח את ה-dentry של /.

3. פתרון "home" - הקרנל מחפש dentry בשם "home" ב-dcache תחת root:
- אם נמצא ב-dcache - מיידי, לא צריך IO.
- אם לא נמצא - הקרנל קורא ל-inode_operations->lookup של תיקיית השורש. מערכת הקבצים (למשל ext4) קוראת מהדיסק את רשימת הentries בתיקיית השורש, מוצאת "home", יוצרת dentry ו-inode, ומכניסה אותם ל-dcache.
- בדיקת הרשאות: האם לתהליך יש הרשאת execute על /? (הרשאת execute על תיקייה פירושה הרשאה לחפש בתוכה).

4. פתרון "user" - אותו תהליך: חיפוש ב-dcache, אם לא נמצא - קריאה מדיסק. בדיקת הרשאות על /home.

5. פתרון "notes.txt" - חיפוש ב-dcache תחת dentry של "user". מציאת ה-inode של הקובץ. בדיקת הרשאות על /home/user.

6. בדיקת הרשאות על הקובץ - הקרנל בודק אם לתהליך (לפי UID ו-GID שלו) יש הרשאת קריאה על notes.txt (כי ביקשנו O_RDONLY).

7. יצירת struct file - הקרנל מקצה struct file חדש (מ-slab cache ייעודי):
- מאתחל את f_pos ל-0 (מיקום תחילת הקובץ)
- מעתיק את f_flags מהדגלים שנתנו (O_RDONLY)
- מחבר את f_op ל-file_operations של מערכת הקבצים (i_fop מה-inode)
- מחבר את f_path ל-dentry ול-mount

8. הקצאת file descriptor - הקרנל מחפש את המספר הנמוך ביותר הפנוי בטבלת ה-file descriptors של התהליך (שלמדנו עליה ב-5.5). מכניס את ה-struct file לתוך הטבלה.

9. החזרה ל-user space - הsyscall מחזיר את מספר ה-file descriptor (למשל 3).

תפקיד ה-dcache: ה-dcache חוסך גישות לדיסק. בלי dcache, כל פתרון נתיב דורש קריאה מהדיסק לכל רכיב בנתיב (3 קריאות דיסק עבור /home/user/notes.txt). עם dcache, אם הנתיב כבר נפתר בעבר, כל הrכיבים כבר בזכרון וה-lookup הוא מיידי. זה קריטי לביצועים כי תוכניות פותחות קבצים כל הזמן.