לדלג לתוכן

הגנה על הפרויקט והרחבה עצמאית

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

ניקח בקשה שהתקבלה דרך Unix socket, הוכנסה ליומן והחזירה תוצאה. נתחיל ב־Vec של parser ונזהה מי מחזיק אותו בזמן קריאה חלקית. נמשיך אל admission permit, אל תור העבודה ואל worker. בזמן append נצביע על ה־File ועל open file description שלו, על offset שמתקדם ועל ההפרדה בין נתונים בזיכרון התהליך, page cache ואחסון עמיד. אחרי sync נבדוק מתי ה־request ID נכנס לאינדקס ומתי מותר לשלוח תשובה.

נאסוף trace מצומצם בתיקיית מעבדה עם נתונים לא רגישים. הפקודה הבאה היא דוגמת הפעלה עבור binary בשם amitjobs, והיא אינה תחליף ל־trace של kernel כאשר השאלה דורשת אותו.

strace -ff -ttT -o trace-job \
  -e trace=accept4,read,write,pread64,pwrite64,fsync,fdatasync,close,epoll_wait \
  ./amitjobs serve ./state

ה־trace יכול להראות write ואחריו fsync, אבל הוא לא יאמר לבדו איזה invariant של המוצר נשמר. נצטרך לקשר fd למקורו, לזהות thread ורגע לוגי, ולבדוק אם ה־write אכן שייך ליומן או ללוג. ה־syscall הוא מעבר למצב kernel, ולא בהכרח context switch לתהליכון אחר. זמן ארוך בקריאה יכול לכלול המתנה או preemption, ולכן נשלים את התמונה באמצעות scheduler trace או perf כאשר זאת השאלה.

המנחה יוסיף תקלה אחת שממוקדת בחוזה, למשל שחרור permit כאשר future מתבטל למרות ש־spawn_blocking ממשיך, שליחת reply לפני sync או פתיחת fd בלי CLOEXEC. נתחיל מתיאור סימפטום, ננסח שתי השערות ונבחר ניסוי שמבדיל ביניהן. הוספת sleep כדי שהמרוץ "ייעלם" אינה תיקון. גם הגדלת timeout אינה הסבר אם ה־owner של המשאב כבר נעלם.

בהרחבה העצמאית נקבל דרישה שלא מומשה בפרויקט, למשל snapshot לקריאה בלבד של תוצאות, תמיכה ב־AArch64 או החלפת backend של המתנה. נתחיל ממפת חוזים: מה חייב להישאר זהה ומה מותר לשנות. עבור snapshot נשאל אם הוא מציג נקודת זמן עקבית, אם הוא מחזיק את היומן בחיים והאם קובץ שהועבר ב־SCM_RIGHTS יכול להשתנות אחרי האימות. כך תכונות שלמדנו בפרקים שונים מתחברות לשאלה אחת שאפשר לבדוק.

נשתמש בתיעוד הרשמי ובמקור של גרסה נעולה. כשנגיע למבנה kernel פנימי לא נציג את השדות שלו כ־ABI יציב לאפליקציה. נבחין בין חוזה userspace מתועד לבין מימוש שיכול להשתנות, ונבחר נקודת אינטגרציה יציבה ככל האפשר. אם כלי דורש nightly או API ניסיוני, נציין את התלות ואת המנגנון החלופי שנשאר זמין.

הדוח הסופי יכיל החלטה ששינינו בעקבות ראיה. למשל ניסוי מראה שה־p99 נובע מ־fsync לכל רשומה, ואז נוכל לבחון group commit תוך שמירת ההבטחה שכל reply נשלח רק אחרי שהקבוצה שלו עמידה. השיפור אינו "הסרנו fsync", אלא שינוי של היחידה שנעשית עמידה והוכחת התאמה של latency, throughput ו־recovery לחוזה החדש.

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