6.7 פסיקות ו exceptions תרגול
תרגיל 1 - בדיקת פסיקות במערכת חיה¶
-
הריצו את הפקודה הבאה:
-
ענו על השאלות הבאות:
- כמה שורות פסיקות חומרה (מספריות) יש?
- מצאו את שורת הטיימר (timer). על איזו ליבה רוב הפסיקות של הטיימר טופלו?
- מצאו את השורה של LOC (Local timer interrupts). מה ההבדל בין הטיימר הגלובלי לLOC?
-
האם יש כרטיס רשת רשום? מה שם הדרייבר שלו?
-
הריצו:
ולחצו מקשים במקלדת. איזה מספר IRQ עולה כשלוחצים?
תרגיל 2 - המסע של לחיצת מקש¶
תארו בפירוט מה קורה מהרגע שמשתמש לוחץ על מקש במקלדת ועד שהתו מופיע על המסך. עברו על כל השלבים:
1. מה קורה ברמת החומרה?
2. איך הפסיקה מגיעה למעבד? (דרך מי?)
3. מה המעבד עושה כשהוא מקבל את הפסיקה?
4. מה הtop half של הhandler עושה?
5. מה הbottom half עושה?
6. איך המידע מגיע בסופו של דבר לתהליך (לטרמינל)?
תרגיל 3 - דיבאגר ו-breakpoints¶
-
הסבירו מה ההבדל בין hardware breakpoint ל-software breakpoint.
-
כשGDB שם software breakpoint בכתובת מסוימת, הוא כותב את הבית
0xCC(הopcode שלint3) במקום הפקודה המקורית.
ענו:
- למה GDB צריך לשמור את הבית המקורי שהיה שם?
- מה קורה כשהמעבד מגיע לint3? תארו את השרשרת: exception -> IDT -> handler -> סיגנל -> ptrace -> GDB
- כשGDB מחליט להמשיך (continue), מה הוא צריך לעשות לפני שהתוכנה ממשיכה?
- בפרק 5.4 למדנו על סיגנלים. הסבירו למה דווקא SIGTRAP הוא הסיגנל שנבחר לbreakpoints ולא סיגנל אחר.
תרגיל 4 - חצי עליון מול חצי תחתון¶
לפניכם שלושה תרחישים. לכל תרחיש, החליטו איזה מנגנון bottom half הכי מתאים (softirq, tasklet, או workqueue) והסבירו למה:
-
דרייבר של כרטיס רשת שצריך לעבד חבילות בקצב של מיליון חבילות בשנייה. העיבוד לא דורש גישה לדיסק.
-
דרייבר של מקלדת USB שצריך לעבד לחיצות מקשים. הקצב נמוך (כמה עשרות לחיצות בשנייה לכל היותר) והעיבוד פשוט.
-
דרייבר של דיסק שצריך לעדכן מטא-דאטה של מערכת הקבצים אחרי כל כתיבה. העדכון דורש הקצאת זיכרון ועשוי לדרוש גישה לדיסק.
תרגיל 5 - חריגות וסיגנלים¶
- לפניכם קטע קוד ב-C. לכל שורה מסומנת, ציינו: איזו חריגה (exception) תיגרם, מה המספר שלה, ואיזה סיגנל יישלח לתהליך.
#include <stdio.h>
#include <signal.h>
int main() {
// שורה A
int x = 1 / 0;
// שורה B
int *ptr = (int *)0xDEADBEEF;
*ptr = 42;
// שורה C
void (*func)() = (void (*)())0x12345678;
func();
return 0;
}
-
כתבו תוכנה ב-C שרושמת signal handler לSIGFPE, ובhandler מדפיסה הודעה ואז יוצאת מהתוכנה. אחרי רישום הhandler, גרמו בכוונה לחלוקה באפס.
-
הסבירו: למה exception #PF (page fault) לא תמיד גורם לSIGSEGV? תנו שתי דוגמאות שבהן page fault הוא "רגיל" והקרנל מטפל בו בלי לשלוח סיגנל.