מעמקי הקלט/פלט ב-Windows (פרק 5) — המבנה הפנימי של NTFS: מערכת קבצים מתוך הבנת MFT
· Go Komura · Windows, NTFS, I/O, מערכת קבצים, MFT, ליבה, .NET, חקירת תקלות
בארבעת הפרקים עד כאן עקבנו אחרי איך בקשת קלט/פלט זורמת (פרקים 1–3) ואיך מנהל המטמון מקבל אותה (פרק 4). בסוף הבקשה מגיעה למערכת הקבצים. הפעם תור הדוגמה המובילה שלה, NTFS.
נקודת המבט משתנה. עד עכשיו הסיפור היה דינמי — זרימת בקשה. הפעם זה סיפור סטטי על איך נתונים מסודרים בדיסק. הזהות האמיתית של «Zone.Identifier» הבלתי נראה שמצורף לקובץ שהורד. למה העתקת עשרת אלפים קבצים קטנים איטית בהרבה מהעתקת קובץ אחד באותו גודל כולל. עד כמה באמת נכון ש«NTFS עם יומן, אז זה בטוח» — הכול ניתן להסביר מהמבנה הזה.
זה פרק 5 בסדרה «מעמקי הקלט/פלט ב-Windows».
הנחה לפרק הזה: עוזר שכבר יש אחיזה ביסודות IRP ומחסנית ההתקנים מפרק 1. עם זאת, כדי שהמאמר יעמוד לבדו, הנה הגדרות למונחים מפרקים קודמים שמופיעים בגוף להלן.
| מונח | בשורה אחת | פירוט |
|---|---|---|
| IRP (I/O Request Packet) | «תלוש בקשת הקלט/פלט» שקריאת API כמו ReadFile מומרת אליו בתוך הליבה. מנהלים מקבלים את התלוש הזה ופועלים עליו |
פרק 1 |
| מנהל הקלט/פלט ומחסנית ההתקנים | רכיב הליבה שיוצר את ה-IRP ומעביר אותו, לפי הסדר, במחסנית המנהלים שערומים בדרך להתקן היעד — והמחסנית עצמה | פרק 1 |
| מנהל המטמון | הרכיב ששומר את תוכן הקובץ בזיכרון ואחר כך שוטף לדיסק את התוכן שהצטבר מקריאות WriteFile. שורש «עצם זה שכתבתם אינו אומר שהגיע לדיסק» |
פרק 4 |
טבלה 1: מונחים מפרקים קודמים שמונחים בפרק הזה
עוד דבר, שני השלבים שטופלו בפרק 1 — cleanup (כשנסגר ה-handle האחרון) ו-close (כשכל ההפניות בתוך הליבה נעלמו) — ישמשו בהסבר מחיקת קבצים בפרק 4.
1. השורה התחתונה קודם
- מרכז NTFS הוא MFT (Master File Table). כל הקבצים מנוהלים כרשומות בפנקס בתוך MFT, וכל המידע על קובץ נמצא «בתוך רשומת MFT» או «באזור מחוץ ל-MFT שהרשומה מצביעה עליו» (פרק 2).1
- ישות הקובץ היא «אוסף מאפיינים». קובץ קטן נכנס כולו, כולל גוף הנתונים, לרשומת MFT (תושב), וקובץ גדול מחזיק רק הפניה לעמודת אשכולות (לא-תושב). האיטיות של עיבוד המוני של קבצים קטנים מוסברת מכאן (פרק 2).1
- אפשר להחזיק כמה נתונים (כמה זרמי נתונים). הנתונים הרגילים הם «זרם חסר שם», ואפשר להחזיק זרם נוסף ב-
שםקובץ:שם. זהות Zone.Identifier (Mark of the Web) (פרק 3).2 - גם שם הוא מאפיין. כמה שמות לאותה רשומה הם קישור קשיח. גם שם מקוצר 8.3 מתגורר כ«עוד שם» (פרק 4).34
- נקודת reparse היא המנגנון הרשמי של «כשפותחים, מקום אחר». קישור סימבולי, junction וקבצים לפי דרישה ב-OneDrive כולם יישומים של הנתונים המתויגים האלה (פרק 5).56
- יש שני יומנים.
$LogFileהוא לשחזור עקביות מטא-נתונים (יומן מקדים כדי לא להישבר), יומן USN הוא לרישום היסטוריית שינויים (פנקס של מה השתנה). התפקידים שונים לגמרי (פרק 6).78 - «גודל» ו«גודל בדיסק» הם דברים שונים. קבצים דלילים ודחיסה יוצרים את הפער. גם הרקע ל«קובץ דחוס אינו הופך לאסינכרוני» שראינו בפרק 2 נמצא כאן (פרק 7).910
מפת הידע של המאמר
מרכז NTFS הוא ה-MFT (טבלת הקבצים הראשית), וכל הקבצים מנוהלים כרשומות בפנקס שבתוך ה-MFT. נתונים קטנים תושבים בתוך הרשומה, ונתונים גדולים הופכים ללא-תושבים ומחזיקים רק הפניה לרצף אשכולות (רצף נתונים) — וזהו מקור האיטיות בטיפול בהמון קבצים קטנים ושל הפיצול. כמה זרמי נתונים, קישור קשיח ושמות מקוצרים 8.3 הם כולם יישומים של אותו מנגנון «אוסף מאפיינים»; נקודת ניתוח מחדש היא ה-hook הרשמי על «פתיחה» שתומך מקישור סמלי ועד קבצים לפי דרישה של OneDrive. מה ש-$LogFile מגן עליו הוא עקביות המבנה; עמידות תוכן הנתונים צריך לבנות בנפרד בכלי בקרת המטמון של החלק הרביעי.
flowchart LR
accTitle: מפת הידע של המבנה הפנימי של NTFS ושל MFT
accDescr: תרשים שמראה את הקשרים בין NTFS, MFT, רשומת קובץ, מאפיינים תושבים ולא-תושבים, רצפי נתונים, פיצול, כמה זרמי נתונים, Zone.Identifier, קישור קשיח, שמות מקוצרים 8.3, נקודות ניתוח מחדש (קישור סמלי, צומת, קבצים לפי דרישה של OneDrive), $LogFile ויומן USN, קבצים דלילים ודחיסת NTFS
ntfs["NTFS"]
mft["MFT (טבלת הקבצים הראשית)"]
mft_record["רשומת קובץ של MFT"]
mft_zone["אזור MFT"]
fragmentation["פיצול (NTFS)"]
resident_attribute["מאפיין תושב (resident)"]
non_resident_attribute["מאפיין לא-תושב (non-resident)"]
data_run["רצף נתונים (data run)"]
fsutil["fsutil"]
alternate_data_stream["זרם נתונים חלופי (ADS)"]
zone_identifier["Zone.Identifier (Mark of the Web)"]
streams_tool["streams (Sysinternals)"]
size_disk_usage_mismatch["פער בין גודל לוגי לשימוש בדיסק"]
hard_link["קישור קשיח"]
eight_dot_three_name["שם מקוצר 8.3"]
reparse_point["נקודת ניתוח מחדש (reparse point)"]
symbolic_link["קישור סמלי"]
junction["צומת (נקודת עגינה)"]
onedrive_files_on_demand["קבצים לפי דרישה של OneDrive"]
ntfs_logfile["$LogFile (יומן העסקאות של NTFS)"]
volume_corruption["פגיעה בכרך"]
cache_manager["מנהל המטמון"]
usn_journal["יומן USN (יומן השינויים)"]
sparse_file["קובץ דליל"]
ntfs_compression["דחיסת NTFS"]
asynchronous_io["קלט/פלט אסינכרוני"]
procmon["Process Monitor(procmon.exe)"]
ntfs -->|"משתמש ב"| mft
mft -->|"משתמש ב"| mft_record
mft -->|"מחייב"| mft_zone
mft_zone -.->|"מצמצם"| fragmentation
mft_record -->|"משתמש ב"| resident_attribute
mft_record -->|"משתמש ב"| non_resident_attribute
resident_attribute -->|"אינו מתיישב עם"| non_resident_attribute
non_resident_attribute -->|"משתמש ב"| data_run
data_run -.->|"עלול לגרום ל"| fragmentation
fragmentation -->|"נבדק באמצעות"| fsutil
ntfs -->|"משתמש ב"| alternate_data_stream
zone_identifier -->|"נשמר ב"| alternate_data_stream
zone_identifier -->|"נבדק באמצעות"| streams_tool
alternate_data_stream -->|"נבדק באמצעות"| streams_tool
alternate_data_stream -.->|"עלול לגרום ל"| size_disk_usage_mismatch
ntfs -->|"משתמש ב"| hard_link
hard_link -->|"מחייב"| mft_record
ntfs -.->|"משתמש ב"| eight_dot_three_name
eight_dot_three_name -->|"מוגדר באמצעות"| fsutil
ntfs -->|"משתמש ב"| reparse_point
reparse_point -->|"נבדק באמצעות"| fsutil
symbolic_link -->|"מממש את"| reparse_point
junction -->|"מממש את"| reparse_point
onedrive_files_on_demand -->|"מממש את"| reparse_point
ntfs -->|"משתמש ב"| ntfs_logfile
ntfs_logfile -->|"מצמצם"| volume_corruption
ntfs -->|"משתמש ב"| cache_manager
ntfs -->|"משתמש ב"| usn_journal
usn_journal -->|"נבדק באמצעות"| fsutil
ntfs -->|"משתמש ב"| sparse_file
sparse_file -->|"עלול לגרום ל"| size_disk_usage_mismatch
ntfs -->|"משתמש ב"| ntfs_compression
ntfs_compression -->|"עלול לגרום ל"| size_disk_usage_mismatch
ntfs_compression -->|"אינו מתיישב עם"| asynchronous_io
ntfs -->|"נבדק באמצעות"| procmon
בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 35, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle
2. הכול הוא רשומת MFT
2.1. הפנקס של הכרך
כשמפרמטים כרך NTFS, נוצרים MFT (master file table) וסדרת קובצי מטא-נתונים שמתחילים ב-$. ב-MFT יש לפחות רשומה אחת לכל קובץ בכרך, וגם רשומה של MFT עצמה כלולה.1
flowchart TB
subgraph VOL["כרך NTFS"]
MFT["$MFT ── טבלת הקבצים הראשית<br/>פנקס רשומות כל הקבצים(גם היא עצמה רשומה)"]
LOG["$LogFile ── יומן עסקאות של<br/>פעולות מטא-נתונים(פרק 6)"]
BITMAP["$Bitmap ── מצב השימוש באשכולות"]
OTH["$Boot / $Secure / $UpCase וכו'<br/>קובצי מטא-נתונים אחרים"]
DATA["אזור נתוני משתמש<br/>(מקום הנחת נתונים לא-תושבים)"]
end
MFT -->|"הרשומה מצביעה על המיקום"| DATA
איור 1: מבנה כרך NTFS. «גם מידע הניהול של מערכת הקבצים עצמה מוחזק כקובץ» הוא תכנון NTFS
המידע על קובץ — גודל, חותמות זמן, הרשאות גישה, ואפילו תוכן הנתונים — נשמר בתוך רשומת MFT, או באזור מחוץ ל-MFT שהרשומה מתארת את מיקומו.1 כשמוחקים קובץ הרשומה מסומנת כ«פנויה» וממוחזרת, אבל MFT עצמה אינה מצטמצמת. בנוסף, כדי לשמור על MFT רציפה שמור אזור שנקרא אזור MFT, וכשהכרך מתמלא מתחיל פיצול של MFT — גם סיפור אורך החיים הזה כתוב בתיעוד הרשמי.1
2.2. קובץ = אוסף מאפיינים, תושב ולא-תושב
תוכן רשומת הקובץ הוא רשימת מאפיינים. מידע תקני (חותמות זמן וכו’), שם קובץ, אבטחה, ואז נתונים. כאן יש פיצול חשוב.
flowchart TB
subgraph REC["רשומת קובץ MFT(פנקס של קובץ אחד)"]
STD["מאפיין מידע תקני<br/>חותמות זמן · דגלי מאפיינים"]
FN["מאפיין שם קובץ<br/>(אפשר כמה ── פרק 4)"]
DATA["מאפיין נתונים"]
end
Q{"האם הנתונים קטנים"}
RES["תושב(resident)<br/>גוף הנתונים נכנס לרשומה<br/>הקריאה מסתיימת בגישה ל-MFT בלבד"]
NONRES["לא-תושב(non-resident)<br/>ברשומה רק «הפניה לעמודת אשכולות»<br/>הנתונים האמיתיים באזור נתוני המשתמש"]
DATA --> Q
Q -->|"עד כמה מאות בתים"| RES
Q -->|"מעבר לזה"| NONRES
איור 2: רשומת קובץ היא אוסף מאפיינים. אם הנתונים קטנים הם «תושבים» בתוך הרשומה
קל יותר לראות איך תוכן אותה רשומה משתנה בין תושב ללא-תושב כשמניחים זה לצד זה.
flowchart LR
subgraph RES2["תושב(resident) ── קובץ קטן"]
RA["רשומת קובץ MFT(אורך קבוע)<br/>מידע תקני / שם קובץ / אבטחה<br/>─────────────<br/>מאפיין נתונים = התוכן עצמו<br/>『ערך הגדרה=1』 נכנס לכאן ישירות"]
RB["אין מקום הנחה נפרד בדיסק<br/>הקריאה מסתיימת בגישה ל-MFT בלבד"]
RA --> RB
end
subgraph NON2["לא-תושב(non-resident) ── קובץ גדול"]
NA["רשומת קובץ MFT(אורך קבוע)<br/>מידע תקני / שם קובץ / אבטחה<br/>─────────────<br/>מאפיין נתונים = טבלת ריצות נתונים<br/>רצף 『מאיפה כמה אשכולות』"]
NB["אזור נתוני משתמש<br/>ריצה 1: אשכולות רציפים"]
NC["אזור נתוני משתמש<br/>ריצה 2: אשכולות רציפים במקום אחר"]
NA -->|"מצביע על המיקום"| NB
NA -->|"מצביע על המיקום"| NC
end
איור 3: השוואת תושב ולא-תושב. בלא-תושב, מה שיש לרשומה הוא רק הטבלה של «איפה וכמה נתונים אמיתיים» (ריצות נתונים)
ככל שמספר ריצות הנתונים גדל, קריאת קובץ אחד דורשת לעבור באזורים מפוזרים. זו זהות הפיצול שמופיעה בהמשך.
מהמבנה הזה אפשר להסביר כמה תופעות שפוגשים בשטח.
- למה העתקת 10,000 קבצים קטנים איטית. לכל קובץ מתרחשות פעולות מטא-נתונים של יצירת רשומת MFT, רישום שם והגדרת אבטחה. עבודת הפנקס שולטת יותר מהעברת הנתונים עצמה (ואז כל אחת מהן הופכת גם ליעד לבדיקת המסננים שנראה בפרק 6).
- זהות הפיצול. נתונים לא-תושבים נרשמים כ«עמודת קטעי אשכולות רציפים (ריצות)». אם אי אפשר לקבל אזור רציף, מספר הריצות גדל ומספר החיפושים הנדרשים לקריאה גדל — זה פיצול. את סידור הריצות בפועל אפשר להציץ ב-
fsutil file layout. - גם «תיקייה» אינה מיוחדת. ספרייה היא «קובץ שמחזיק אינדקס משם קובץ למספר רשומת MFT». על הפנקס, הכול יושב על אותו מנגנון.
3. נתונים הם רק אחד מ«הזרמים»
3.1. קובץ אחד, כמה רצפי בתים
ב-NTFS קובץ אחד יכול להחזיק כמה זרמי נתונים. מה שקוראים וכותבים בדרך כלל ב-ReadFile/WriteFile הוא זרם ברירת המחדל חסר השם, ובמשפט שםקובץ:שםזרם אפשר ליצור זרם נתונים חלופי (ADS).2
flowchart LR
subgraph F["הקובץ report.docx(רשומת MFT אחת)"]
D0["זרם ברירת מחדל(חסר שם)<br/>= התוכן שרואים בדרך כלל"]
D1[":Zone.Identifier<br/>מידע מקור(Mark of the Web)"]
D2[":שם שרירותי<br/>מידע נוסף ייחודי ליישום"]
end
איור 4: כמה זרמי נתונים. מה שמופיע בתצוגת הגודל בסייר הוא רק זרם ברירת המחדל
ה-ADS הקרוב ביותר הוא Zone.Identifier. לקובץ שהורד בדפדפן נרשם בזרם הזה המקור (שמקורו באינטרנט וכו’), והוא הופך לחומר שיפוט ל«Windows הגנה על המחשב» של SmartScreen ולתצוגה מוגנת של Office. הצד הגלוי של המנגנון הזה טופל ב«למה מופיע «Windows הגנה על המחשב»» — הזהות מאחורי הקלעים הייתה פשוט זרם NTFS.
3.2. המלכודות שמפתחים דורכים עליהן
- בלתי נראה. אינו מופיע בגודל בסייר וגם לא ברשימת
dir. אפשר לבדוק ב-dir /rאו ב-streamsשל Sysinternals.11 - אינו ניתן להעברה. ADS הוא תכונת NTFS, ולכן בהעתקה דרך כונן USB ב-FAT או אחסון ענן הוא נוטה להיאבד. «אזהרת ההורדה נעלמה אחרי שהעתקתי» זה זה.
- אפשר לפתוח גם ביישום שלכם. די לכלול נקודתיים בנתיב כמו
CreateFile("data.txt:meta", ...)כדי לקרוא ולכתוב.2 זה נוח, אבל מקבלים יחד את תכונת «אינו ניתן להעברה» מהסעיף הקודם, ולכן זה אינו מקום לגוף נתונים עסקיים.
4. גם שם הוא מאפיין — קישורים קשיחים ושמות 8.3
4.1. קישור קשיח — כמה שמות לאותה רשומה
באיור 2 כתבנו ש«אפשר להחזיק כמה מאפייני שם קובץ». בתוך אותו כרך, כמה נתיבים מפנים לקובץ יחיד — זה קישור קשיח (CreateHardLink / mklink /H).3
flowchart TB
subgraph DIR1["האינדקס של C:\\app\\"]
E1["config.json → רשומה #1234"]
end
subgraph DIR2["האינדקס של C:\\backup\\"]
E2["config-link.json → רשומה #1234"]
end
REC["רשומת MFT #1234<br/>גוף הנתונים(או הפניה לריצות)<br/>מספר קישורים: 2"]
E1 --> REC
E2 --> REC
איור 5: קישור קשיח. אינדקס הספרייה מצביע על אותה רשומת MFT, ושניהם «האמיתי»
שינוי מכל שם שהוא הוא אותו קובץ, ולכן התוכן תואם מיד.3 ואז משמעות «מחיקה» משתנה — DeleteFile הוא «להסיר שם אחד», והישות נעלמת רק כשהשם האחרון הוסר, ה-handle הפתוח נסגר, וגם כל ההפניות בתוך הליבה כמו מקטע מיפוי זיכרון נעלמו. שני השלבים שראינו בפרק 1, cleanup (ה-handle האחרון) ו-close (ההפניה האחרונה), פועלים כמו שהם גם על אורך החיים של המחיקה. שימו לב שיש מוזרות בתצוגת מאפיינים: גם אם משנים מאפיין דרך קישור אחד, התצוגה הנראית של קישור אחר עשויה להישאר ישנה — התנהגות שמצוינת רשמית.3
4.2. שם 8.3 — עוד שם נסתר
לתאימות היסטורית, NTFS יכולה ליצור אוטומטית שם מקוצר בפורמט 8.3 כמו REPORT~1.DOC לשמות קבצים ארוכים. גם זה מתגורר ברשומה כ«עוד שם». בתיקיות עם הרבה קבצים, יצירת השם המקוצר והימנעות מהתנגשות הופכות לעלות, ולכן אפשר להשבית יצירה או להסיר שמות מקוצרים קיימים ב-fsutil 8dot3name (אם יש יישום ישן שרושם נתיבי רישום בשם מקוצר זה נשבר, ולכן יש גם פונקציית בדיקה לפני strip — נקודה מעשית).4
כאן כדאי לשים לב שהאם יש שם מקוצר תלוי בסביבה. התנהגות ברירת המחדל נקבעת בערך הרישום NtfsDisable8dot3NameCreation, ויש ארבע אפשרויות: 0 (ליצור בכל הכרכים), 1 (לא ליצור באף כרך), 2 (להגדיר לפי כרך), 3 (לא ליצור מחוץ לכרך המערכת).4 אם בוחרים 2 אפשר להחליף לפי כרך, כך ש«ב-Windows תמיד קיים שם מקוצר כמו PROGRA~1» אינו בהכרח נכון. לפני שכותבים קוד או נוהל שתלוי בשם מקוצר, בדקו את המצב הנוכחי ב-fsutil 8dot3name query C: (השמטת הכרך מחזירה את ברירת המחדל המשותפת לכל הכרכים).
מלכודות סביב נתיבים ושמות (MAX_PATH, שמות שמורים, נקודה בסוף) מטופלות בפירוט ב«MAX_PATH והמלכודות של נתיבים ושמות קבצים ב-Windows». אם מחברים את פתרון השמות מפרק 1 (מנהל האובייקטים) לפרק הזה (שמות בתוך מערכת הקבצים), מתקבלת התמונה המלאה של «שם» ב-Windows.
5. נקודת reparse — המנגנון של «כשפותחים, מקום אחר»
אפשר לצרף לקובץ או לספרייה נקודת reparse. הישות היא מאפיין של «תג + נתונים שהמשתמש מגדיר». כשמערכת הקבצים פותחת קובץ עם נקודת reparse, העיבוד נחטף לפי התג — מנהל מסנן שמבין את התג לוקח את העיבוד, או בתגי שינוי שם הפתרון מתחיל מחדש בנתיב היעד.5
sequenceDiagram
participant App as יישום
participant IOM as מנהל הקלט/פלט
participant FS as NTFS
App->>IOM: CreateFile("C:\\data\\link.txt")
IOM->>FS: IRP_MJ_CREATE(עולם פרק 1)
Note over FS: נמצאה נקודת reparse ביעד<br/>מחזירים תג ונתונים
alt קישור סימבולי / junction(שינוי שם)
FS-->>IOM: 「המקום האמיתי הוא כאן」
IOM->>FS: פותרים מחדש בנתיב היעד
else תג בניהול מסנן(קובץ ענן וכו')
Note over FS: מסנן שמבין את התג<br/>לוקח את העיבוד(פרק 6)
end
איור 6: פתרון נקודת reparse. זה הופך לוו רשמי שמתערב בפעולת «פתיחה»
על המנגנון האחד הזה עומדות תכונות מוכרות.
- קישור סימבולי (
mklink) — שלט שמחזיק נתיב יעד. יכול להצביע גם לכרך אחר או לנתיב UNC.6 - Junction / נקודת mount — מנגנון ותיק שמחבר ספרייה למיקום בכרך מקומי אחר.3
- קבצים לפי דרישה ב-OneDrive — מייצגים קובץ שאין לו נתונים אמיתיים ביד כנקודת reparse, וברגע הפתיחה המסנן מוריד ומגיש את התוכן. זו זהות «רואים בסייר, אבל כשפותחים רצה תקשורת» (מנגנון המסנן עצמו בפרק 6).
אזהרה מעשית אחת. «המקום שאליו הנתיב מצביע אינו בהכרח המקום המקומי הזה». כלי שעובר עץ באופן רקורסיבי נכנס ללולאה ב-junction, סיכום גדלים נכפל, גיבוי גורם להמון הגשמה של ענן — קוד שלא יודע על נקודות reparse דורך על אלה. אישור המאפיין FILE_ATTRIBUTE_REPARSE_POINT במשפחת FindFirstFile הוא פתח האמצעי.5
6. שני יומנים — $LogFile ו-USN
אומרים לעיתים קרובות «NTFS היא מערכת קבצים עם יומן», אבל ב-NTFS יש שני יומנים עם תפקידים שונים. בלבול ביניהם גורם לקרוא לא נכון את ההבטחה.
flowchart TB
subgraph J1["$LogFile ── יומן מקדים(כדי לא להישבר)"]
A1["רושמים פעולת מטא-נתונים(עדכון רשומה · שינוי שם וכו')<br/>ליומן לפני הביצוע"]
A2["באתחול הבא אחרי כשל מערכת<br/>משחזרים את היומן ומשחזרים עקביות מבנה"]
A1 --> A2
end
subgraph J2["יומן USN ── היסטוריית שינויים(כדי לדעת מה השתנה)"]
B1["בכל שינוי לקובץ / ספרייה<br/>רושמים את תוכן השינוי ואת השם"]
B2["גיבוי · אינדקס חיפוש · כלי סנכרון<br/>תופסים 「מה השתנה מהפעם הקודמת」 בלי סריקה מלאה"]
B1 --> B2
end
איור 7: שני היומנים. $LogFile הוא «כדי לא להישבר», USN הוא «כדי לדעת מה השתנה»
ההבדל בטבלה הוא כדלקמן.
| היבט | $LogFile (יומן עסקאות) |
יומן USN (יומן שינויים) |
|---|---|---|
| מטרה | להחזיר את מבנה מערכת הקבצים למצב עקבי אחרי כשל7 | לדעת אחר כך «מה השתנה מהפעם הקודמת»8 |
| מה נרשם | יומן מקדים של פעולות מטא-נתונים (עדכון רשומה, שינוי שם וכו’). תוכן הקובץ אינו יעד | בכל שינוי, תוכן השינוי ושם הקובץ/ספרייה היעד8 |
| מי משתמש | NTFS עצמה. לשימוש בשחזור אוטומטי ב-mount הבא | יישומים כמו גיבוי, אינדקס חיפוש וכלי סנכרון |
| עד כמה אפשר לחזור אחורה | רק הטווח הנדרש לשחזור. גודל קבוע שממוחזר, ולכן אינו מתאים למעקב היסטוריה | כשחורגים מגודל היעד (MaximumSize) רשומות ישנות נגזרות בנקודת ביקורת. הטווח שניתן לחזור אליו תלוי בהגדרת הגודל ובכמות העדכונים בכרך12 |
| איך מעיינים | אין אמצעי רשמי לקרוא את התוכן (אפשר לבדוק גודל ב-chkdsk /L) |
מצב ב-fsutil usn queryjournal, תוכן ב-fsutil usn readjournal. מתוכנית FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL12 |
| אפשר לעצור? | אי אפשר (חלק מ-NTFS) | מנהל יכול למחוק ולהשבית. אבל זה כופה סריקה מלאה על שירותים בשימוש, וההשפעה גדולה12 |
טבלה 2: השוואת שני היומנים
$LogFile(יומן עסקאות) הוא יומן מקדים של פעולות מטא-נתונים. גם אם מתרחש כשל מערכת, NTFS משחזרת אוטומטית את עקביות מערכת הקבצים מהיומן הזה וממידע נקודת הביקורת באתחול הבא.7 מה שמוגן כאן הוא המבנה. כפי שראינו בפרק 4, תוכן נתונים מלוכלך במטמון יכול להיאבד בהפסקת חשמל — «הכרך לא יישבר. אבל הכתיבה האחרונה יכולה להיעלם» היא הקריאה הנכונה.- יומן USN (יומן שינויים) הוא פנקס שרושם בכל שינוי לקובץ או לספרייה בכרך את תוכן השינוי ושם היעד.8 זה מנגנון לגיבוי ולמאבדקים לאסוף «רק מה שהשתנה מהפעם הקודמת» בלי סריקה מלאה, ומשמש גם להימנעות מבנייה מחדש של אינדקס אחרי כשל.8 בפועל, כדאי לזכור שאפשר להשתמש ב-
fsutil usn readjournalכפנקס הצלבה שמשלים פספוסים שלFileSystemWatcher(«מדריך מעשי ל-FileSystemWatcher») בחקירה.
7. דליל ודחיסה — הסיפור שבו יש שני «גדלים»
ב-NTFS, האורך הלוגי של קובץ והאזור שהוקצה בפועל מנוהלים בנפרד. «גודל» ו«גודל בדיסק» במסך המאפיינים. שני נציגים יוצרים את הפער.
קובץ דליל אינו מקצה אזור אמיתי לטווחים שנמשכים כאפסים ומנהל אותם כ«חורים».9 קובץ דיסק וירטואלי בגודל לוגי 42GB שמשתמש רק ב-500MB בדיסק — קורה כדבר שבשגרה. קריאת חור מחזירה אפסים, וכתיבה מקצה רק את החלק הזה.
flowchart LR
subgraph L["קובץ לוגי(גודל: 1GB)"]
R1["נתונים 10MB"]
H1["חור(אפס) 500MB"]
R2["נתונים 5MB"]
H2["חור(אפס) היתרה"]
end
subgraph P["הקצאה בדיסק(15MB+מידע ניהול)"]
A1["ריצה: ישות R1"]
A2["ריצה: ישות R2"]
end
R1 --> A1
R2 --> A2
איור 8: קובץ דליל. ל«חורים» אין הקצאה, והגודל הלוגי והגודל בדיסק מתרחקים
דחיסת NTFS דוחסת ומאחסנת נתונים לפי יחידת דחיסה.10 זה שקוף ונוח, אבל גם העלות אינה שקופה — בכל קריאה וכתיבה רצים פריסה ודחיסה מחדש, וגם פיצול מתקדם בקלות. וכפי שראינו בפרק 2 פרק 5, גישה לקובץ דחוס אינה הופכת לאסינכרונית (מערכת הקבצים ממירה לסינכרוני). זה אחד המקומות לחשוד כש«יש קובץ שהפכתי לקלט/פלט אסינכרוני והוא לא מאיץ».
את הגודל האמיתי מבוסס ההקצאה אפשר לקבל ב-GetCompressedFileSize. בחקירת «סכום גדלי הקבצים» ו«שימוש בדיסק» לא תואמים, הנוהל הקבוע הוא לחשוד לפי הסדר בארבעה: דליל, דחיסה, ADS (פרק 3), ועיגול לאשכול.
8. לאשר במו עיניכם
גם הפעם אפשר לצפות בהכול ב-Windows שבידכם (חלק דורש הרשאות מנהל). כדי שתוכלו לשפוט בעצמכם אם תוצאת ההרצה נכונה, נצרף לכל פקודה איפה להסתכל ומה זה אומר.
:: לראות זרמי נתונים חלופיים
dir /r C:\Users\%USERNAME%\Downloads
כאן מסתכלים: מתחת לשורת הקובץ הרגילה מופיעות בשורה עם הזחה שורות בצורה שםקובץ:Zone.Identifier:$DATA עם אורך. אם יש שורה כזו, לקובץ הזה מצורף Mark of the Web (פרק 3). לקובץ שהורד בדפדפן זה מצורף, לקובץ שיצרתם בעצמכם לא. הרצה בשני המקומות והשוואה מבהירה את קיום ADS.
:: לראות את פריסת הקובץ (ריצות) ואת המאפיינים ב-MFT
fsutil file layout C:\path\to\file.dat
:: לראות extents בלבד (תת-פקודה המתועדת רשמית)
fsutil file queryextents C:\path\to\file.dat
כאן מסתכלים: layout מציג לכל זרם גודל, גודל מוקצה, ואם לא-תושב — רשימת extents (זוגות VCN, LCN ומספר אשכולות). קובץ קטן מאוד בלי שורות extent הוא תושב (סעיף 2.2); אם מתפצל לכמה שורות, הוא מפוצל. הדרך הקצרה ביותר לחוש תושב/לא-תושב היא להריץ על קובץ טקסט של כמה בתים ועל קובץ של מאות MB ולהשוות.
:: הגדרת יצירת שם מקוצר 8.3 ושמות מקוצרים קיימים
fsutil 8dot3name query C:
dir /x
כאן מסתכלים: query מחזיר אם יצירת שם מקוצר פעילה או מושבתת בכרך הזה (השמטת הכרך מחזירה את ברירת המחדל המשותפת לכל הכרכים).4 dir /x מציג עמודת שם מקוצר ליד השם הארוך, כך שעמודה ריקה פירושה שלא נוצר שם מקוצר. אפשר לאשר בסביבה שלכם את «אין בהכרח שם מקוצר» מסעיף 4.2.
:: מצב יומן USN
fsutil usn queryjournal C:
כאן מסתכלים: מוצגים מזהה היומן, טווח USN התקף (First USN / Next USN), גודל יעד (MaximumSize) ויחידת הקצאה (AllocationDelta).12 אם יוצרים קובץ כלשהו ומריצים שוב, Next USN אמור להתקדם, וזה אישור ש«השינוי נרשם». MaximumSize הוא מדד ל«עד כמה אפשר לחזור אחורה» שנגענו בו בפרק 6. בכרך שבו היומן מושבת מתקבלת שגיאה.
:: אישור נקודות reparse (יעד ותג)
dir /aL C:\Users\%USERNAME%
fsutil reparsepoint query "C:\Users\%USERNAME%\OneDrive"
כאן מסתכלים: מה שמופיע ב-dir /aL הם נקודות reparse (אלה ש-FILE_ATTRIBUTE_REPARSE_POINT דולק בהן). קישור סימבולי או junction מוצגים עם סוג כמו <SYMLINKD> <JUNCTION>. fsutil reparsepoint query מציג את ערך תג ה-reparse, ובסוג שינוי שם גם את נתיב היעד. ציון יעד שאינו נקודת reparse מחזיר שגיאה, כך שעצם השגיאה היא אישור ש«כאן זו תיקייה רגילה».
כשעוקבים אחרי פעולות קבצים ב-Procmon, הדמויות של הפרק הזה זורמות בשמן האמיתי (כתיבה ל-$LogFile, נתיבים עם שם זרם, עיבוד reparse). לשימוש ראו «מדריך מעשי ל-Process Monitor (ProcMon)».
9. סיכום
- מרכז NTFS הוא MFT. כל הקבצים הם רשומות בפנקס, והמידע נמצא «בתוך הרשומה» או «באזור חיצוני שהרשומה מצביעה עליו». נתונים קטנים הם תושבים, נתונים גדולים הם הפניית ריצה, והאיטיות של עיבוד המוני של קבצים קטנים והפיצול הם מסקנות מהמבנה הזה.1
- אפשר להחזיק כמה זרמי נתונים. Zone.Identifier (Mark of the Web) הוא פשוט ADS, נראה ב-
dir /r, ואינו מועבר מחוץ ל-NTFS.211 - שם הוא מאפיין, ואפשר כמה. קישור קשיח הוא שם באותו מעמד לאותה רשומה, ושם 8.3 הוא עוד שם לתאימות. «מחיקה = הסרת שם», והישות נעלמת כשכל השמות, ה-handles וההפניות בתוך הליבה (מקטעים ממורכבים וכו’) נעלמו.34
- נקודת reparse היא וו רשמי ל«פתיחה», וגם קישור סימבולי, junction וקבצים לפי דרישה הם יישום של זה. קוד שעובר עץ צריך להיות מודע ל-
FILE_ATTRIBUTE_REPARSE_POINT.56 - יש שני יומנים.
$LogFileהוא שחזור עקביות מבנה (לא להישבר), USN הוא היסטוריית שינויים (מה השתנה). «יש יומן ולכן גם הנתונים בטוחים» אינו נכון — עמידות הנתונים בונים בכלים מפרק 4.78 - גודל לוגי והקצאה הם דברים שונים. דליל, דחיסה, ADS ועיגול לאשכול הם ארבעת הגורמים העיקריים ל«הגודל לא תואם». כולל העניין שקובץ דחוס אינו הופך לקלט/פלט אסינכרוני, זה מגירה לחקירת ביצועים.910
ההמשך הוא הפרק האחרון, פרק 6 «מנהלי מסנן ומיניפילטר — למה Procmon וסריקת אנטי-וירוס יכולים להתערב בקלט/פלט». אלה ש«יושבים באמצע» שהופיעו מפרק 1 מדי פעם — אנטי-וירוס, Procmon, OneDrive, הצפנה — איך הם מתערבים בקלט/פלט. כסיום הסדרה, נחשוף את זהות הדיירים שעומדים ברווח של מחסנית ההתקנים.
מאמרים קשורים
- מעמקי הקלט/פלט ב-Windows (פרק 1) — כל קריאה וכתיבה הופכות ל-IRP: התמונה הכללית של מערכת הקלט/פלט
- מעמקי הקלט/פלט ב-Windows (פרק 2) — קלט/פלט סינכרוני ואסינכרוני: המשמעות האמיתית של OVERLAPPED
- מעמקי הקלט/פלט ב-Windows (פרק 4) — מנהל המטמון: מתי ה-WriteFile שלכם מגיע לדיסק
- למה מופיע «Windows הגנה על המחשב»
- MAX_PATH והמלכודות של נתיבים ושמות קבצים ב-Windows — מגבלת 260 תווים, שמות שמורים, נקודה בסוף, רישיות
- מדריך מעשי ל-FileSystemWatcher — התמודדות עם פספוסים וכפילויות
- המלכודות של כונן רשת ונתיב UNC — תפעול שרת קבצים (תיקייה משותפת) ביישום עסקי
- מדריך מעשי ל-Process Monitor (ProcMon) — לאתר ב-10 דקות «ההגדרה לא נקראת» ו«ACCESS DENIED»
תחומי ייעוץ קשורים
KomuraSoft LLC מטפלת בתכנון וחקירה של יישומים עסקיים ל-Windows ששורשיהם במנגנון NTFS, כמו התנהגות בלתי מובנת של גודל קובץ או ביצועי העתקה, ותקלות סביב קישורים וזרמים.
מקורות
-
Microsoft Learn, Master File Table. על כך שלכל קובץ בכרך NTFS יש לפחות רשומה אחת ב-MFT, וגם רשומת MFT עצמה כלולה; על כך שכל המידע כולל גודל קובץ, חותמות זמן, הרשאות גישה ותוכן נתונים נשמר בתוך רשומת MFT או באזור מחוץ ל-MFT שהרשומה מתארת את מיקומו; על כך שבמחיקת קובץ הרשומה מסומנת כפנויה וממוחזרת אבל גודל MFT אינו מצטמצם; על כך ששמור אזור MFT כדי לשמור על MFT רציפה; ועל כך שעם התקדמות ההקצאה מתרחש פיצול של MFT. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, File Streams. על כך שנתוני קובץ NTFS מאוחסנים כזרם אחד או יותר; על כך שיש זרם נתונים ברירת מחדל (חסר שם) וזרמי נתונים חלופיים בעלי שם; ועל כך שאפשר לציין זרם בצורת «שםקובץ:שםזרם» ולפתוח ב-CreateFile. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Hard links and junctions. על כך שקישור קשיח הוא ייצוג במערכת הקבצים שבו כמה נתיבים באותו כרך מפנים לקובץ יחיד; על יצירה ב-CreateHardLink; על כך ששינוי דרך כל קישור נראה מיד מקישורים אחרים; על כך ששינוי מאפיינים מתפשט לכל הקישורים הקשיחים, אבל התצוגה ברשומת הספרייה מתעדכנת רק בקישור שבו בוצע השינוי; ועל junction (מנגנון שמחבר ספרייה לכרך מקומי אחר). ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, fsutil 8dot3name. על כך ש-NTFS יכולה ליצור שם מקוצר בפורמט 8.3 לשמות קבצים ארוכים; ועל כך שב-fsutil 8dot3name אפשר לשאול ולהגדיר הפעלה/השבתה של יצירת שם מקוצר, להסיר שמות מקוצרים קיימים (strip), ולסרוק הפניות רישום שיושפעו אם מסירים. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Reparse points. על כך שנקודת reparse היא אוסף של נתונים שהמשתמש מגדיר ותג reparse שמזהה באופן ייחודי את פורמט הנתונים; על כך שבפתיחת קובץ עם נקודת reparse מערכת הקבצים מנסה עיבוד שתואם לתג (עיבוד בידי מסנן מערכת קבצים שמפרש את התג); על כך שהיא משמשת למימוש קישורי מערכת קבצים של NTFS ולאחסון מרוחק (זיכרון היררכי); ועל כך שאפשר לאשר קיום במאפיין FILE_ATTRIBUTE_REPARSE_POINT. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Symbolic links. על כך שקישור סימבולי הוא אובייקט מערכת קבצים שמצביע לקובץ או לספרייה אחרים, ופועל כהפניה שקופה ליעד; ועל כך שיש קישורים מוחלטים ויחסיים, ואפשר הפניה חוצת כרכים או לנתיב מרוחק. ↩ ↩2 ↩3
-
Microsoft Learn, NTFS overview. על כך ש-NTFS משתמשת בקובץ יומן ובמידע נקודת ביקורת, ובמקרה של כשל מערכת משחזרת את יומן העסקאות באתחול הבא ומשחזרת אוטומטית את עקביות מערכת הקבצים; ועל כך שיש מיפוי דינמי מחדש של סקטורים פגומים, ו-self-healing NTFS שמתקן נזק קל ברקע. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Change Journals. על כך שבכל שינוי לקובץ או לספרייה בכרך נרשמים תוכן השינוי ושם הקובץ/ספרייה היעד ביומן השינויים USN של הכרך; על כך שהיומן נשמר לפי כרך; ועל כך שאפשר להשתמש בו לשחזור אינדקס מערכת קבצים אחרי כשל ולהימנע מאינדוקס מחדש של הכרך כולו. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Sparse Files. על כך שבקובץ דליל לא מקצים שטח דיסק פיזי לטווחים גדולים שמורכבים מאפסים, ומקצים אזור רק לחלקים שמכילים נתונים; ועל כך שקריאת טווח בלי הקצאה מחזירה אפסים. ↩ ↩2 ↩3
-
Microsoft Learn, File Compression and Decompression. על כך שדחיסת קבצים של NTFS נעשית בשקיפות, והנתונים נדחסים ומאוחסנים לפי יחידת דחיסה; על כך שב-GetCompressedFileSize אפשר לקבל את הגודל אחרי דחיסה (הקצאה אמיתית); ועל כך שקריאה וכתיבה של קובץ דחוס מלוות בעלות פריסה ודחיסה מחדש. ↩ ↩2 ↩3
-
Microsoft Learn, Streams - Sysinternals. על כך שכלי העזר streams של Sysinternals יכול למנות ולמחוק זרמי נתונים חלופיים של קובץ NTFS. ↩ ↩2
-
Microsoft Learn, Creating, Modifying, and Deleting a Change Journal ו-fsutil usn. על כך ש-MaximumSize של יומן השינויים הוא ערך יעד, וכשהגודל חורג מסכום MaximumSize ו-AllocationDelta הוא נגזר בנקודת הביקורת של NTFS; על כך ש-AllocationDelta הוא יחידת ההוספה לסוף היומן והמחיקה מההתחלה; על כך שב-fsutil usn queryjournal אפשר לעיין במצב ובקיבולת היומן, וב-readjournal בתוכן הרשום; על כך שמתוכנית משתמשים ב-FSCTL_CREATE_USN_JOURNAL / FSCTL_QUERY_USN_JOURNAL / FSCTL_READ_USN_JOURNAL / FSCTL_DELETE_USN_JOURNAL; ועל כך שמחיקה או השבתה של יומן פעיל מלווה בסריקת MFT כולה וכופה על שירותים שמשתמשים ביומן סריקה מחדש של הכרך. ↩ ↩2 ↩3 ↩4
מאמרים קשורים
מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.
מעמקי הקלט/פלט ב-Windows (פרק 4) — מנהל המטמון: מתי ה-WriteFile שלכם מגיע לדיסק
פרק 4 בסדרה שמסבירה בתרשימים את מנהל המטמון של Windows. מכסה את המטמון שמומש כמיפוי קובץ, קריאה מראש וכתיבה מאוחרת, הבחירה בין FlushFileB...
מעמקי הקלט/פלט ב-Windows (פרק 6, אחרון) — מנהלי מסנן ומיניפילטר: למה Procmon וסורקי אנטי-וירוס יכולים להתערב בקלט/פלט
הפרק האחרון בסדרה שמסבירה בתרשימים מנהלי מסנן ומיניפילטר ב-Windows. הוא מכסה את מנהל המסננים וגבהים (altitude), קריאות חוזרות pre/post, א...
קבצי OneDrive לפי דרישה ויישומים עסקיים — ההנחות שממלאי מקום שוברים וכיצד להתמודד
קובץ CSV בשולחן העבודה לא נפתח, או שייבוא נכשל ב־"הקובץ לא נמצא" — הסיבה עשויה להיות Known Folder Move וקבצים לפי דרישה של OneDrive. המאמ...
שיטות עבודה מומלצות לרב־תהליכוניות בפועל: מהדורת .NET — מה להחליט לפני שמוסיפים תהליכונים
סיכום מעשי של כללי התכנון שמונעים מקוד רב־תהליכוני ב-.NET/C# לקרוס או להיתקע מדי פעם: לעלות על Task במקום ליצור תהליכונים בעצמכם, לצמצם מ...
עותק צל של כרך (VSS): המנגנון והפרקטיקה — למה תוכנת גיבוי מצליחה להעתיק קבצים שעדיין בשימוש
קבצים שבשימוש בדרך כלל אי אפשר להעתיק בגלל הפרת שיתוף — אז איך תוכנת גיבוי מצליחה? המאמר מסביר את תפקידי המבקש, הכותב והספק בשירות Volume...
נושאים קשורים
העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.
נושאים טכניים ב-Windows
שער לנושאי פיתוח Windows, חקירת תקלות וניצול נכסים קיימים.
שירותים הקשורים לנושא הזה
המאמר קשור ישירות לשירותים הבאים.
פיתוח יישומי Windows
יישומים עסקיים, חיבור התקנים וכלי תקשורת, מהגדרת הדרישות ועד הפיתוח.
שאלות נפוצות
שאלות נפוצות בפניות בנושא המאמר.
- מהי MFT (Master File Table)?
- זו מבנה הנתונים בלב כרך NTFS — פנקס שמחזיק לפחות רשומה אחת (רשומת קובץ) לכל קובץ בכרך, כולל רשומה ל-MFT עצמה. כל מה שקשור לקובץ, מגודל, חותמות זמן והרשאות גישה ועד תוכן הנתונים עצמו, נשמר או בתוך רשומת MFT או באזור מחוץ ל-MFT שהרשומה מצביעה עליו. קובץ קטן נכנס כולו, כולל הנתונים, לתוך רשומת ה-MFT שלו (תושב, resident); לקובץ גדול נרשמת ברשומה רק הפניה לפריסת הנתונים (ריצה של אשכולות) (לא-תושב, non-resident). מחיקת קובץ מסמנת את הרשומה כפנויה לשימוש חוזר, אבל גודל ה-MFT עצמו אינו מצטמצם.
- מהם נתוני «Zone.Identifier» הבלתי נראים שמצורפים לקבצים?
- זה אחד מזרמי הנתונים המרובים של NTFS (זרמי נתונים חלופיים). ב-NTFS קובץ אחד יכול להחזיק כמה רצפי בתים (זרמים); מה שקוראים וכותבים בדרך כלל הוא הזרם ברירת המחדל חסר השם. Windows רושם מאיפה הקובץ הגיע — למשל שהורד מהאינטרנט — בזרם נוסף שמציינים בנקודתיים, כמו «file.txt:Zone.Identifier». זה מה שנקרא «Mark of the Web», וזה מה ש-SmartScreen ותצוגה מוגנת של Office משתמשים בו כראיה בשיפוטיהם. זרמים חלופיים אינם מופיעים בתצוגת הגודל בסייר; אפשר לבדוק אותם בפקודה dir /r או בכלי streams של Sysinternals. כדאי גם לשים לב שהם אינם נשמרים כשמעתיקים למערכת קבצים שאינה NTFS כמו FAT.
- מה ההבדל בין קישור קשיח לקישור סימבולי?
- קישור קשיח הוא «עוד שם באותו מעמד שנוסף, מצביע על אותה ישות קובץ — אותה רשומת MFT». אפשר ליצור אותו רק בתוך אותו כרך, גישה לקובץ דרך כל אחד משמותיו נותנת את אותו קובץ, ומחיקת שם אחד אינה מסירה את הקובץ כל עוד שם אחר נשאר. קישור סימבולי הוא «שלט שמפנה לנתיב אחר», ממומש כנקודת reparse. מכיוון שהוא מחזיק רק את נתיב היעד כמחרוזת, הוא יכול להצביע לכרך אחר או אפילו למיקום מרוחק, אבל הופך למבוי סתום אם היעד נעלם. בפועל, כלל האצבע: קישור קשיח לשיתוף הישות הבסיסית (שמשנה את משמעות המחיקה), וקישור סימבולי להפניית נתיב (להעברה או הפניה).
- NTFS היא מערכת קבצים עם יומן, אז הנתונים שורדים הפסקת חשמל?
- צריך להבין בדיוק מה מוגן. מה שיומן העסקאות של NTFS ($LogFile) מגן עליו הוא עקביות מבנה מערכת הקבצים (המטא-נתונים). גם אם מתרחש כשל מערכת, NTFS משחזרת עקביות אוטומטית באמצעות היומן באתחול הבא, ומונעת מצב שבו הכרך פגום ואינו ניתן לקריאה. אבל זה אינו אומר שתוכן הקובץ שהיה באמצע כתיבה משוחזר. כפי שראינו בפרק 4 של הסדרה, נתונים מלוכלכים שיושבים במטמון אובדים בהפסקת חשמל. לכן ההבנה הנכונה היא «הכרך לא יישבר, אבל תוכן הכתיבה האחרונה עדיין יכול להיעלם» — אם נדרשת עמידות לנתונים עצמם, צריך לבנות אותה בעצמכם, עם FlushFileBuffers, WRITE_THROUGH, או תכנון כתיבה ברמת היישום כמו כתיבה לקובץ זמני ואז שינוי שם.
- למה «הגודל» של קובץ שונה מ«הגודל בדיסק»?
- כי NTFS מנהלת בנפרד את האורך הלוגי של הקובץ ואת שטח הדיסק שמוקצה לו בפועל. גם בקובץ רגיל יש הבדל כלשהו כי ההקצאה מעוגלת כלפי מעלה לאשכולות שלמים (4KB כברירת מחדל), אבל קבצים דלילים וקבצים דחוסים הם המקום שבו הפער הופך גדול. קובץ דליל אינו מקצה אחסון אמיתי לטווחים שנמשכים כאפסים — הוא מנהל אותם כ«חורים» — כך שבהחלט אפשרי שקובץ בגודל לוגי של כמה ג'יגה-בתים ישתמש רק בכמה מגה-בתים בדיסק. לקובץ דחוס מוקצה רק הגודל אחרי דחיסה. להפך, אם «הגודל בדיסק» נראה גדול יותר, עיגול לאשכול או זרם נתונים חלופי הם לעיתים קרובות הסיבה.