דיבוג קרנל - תרגול¶
תרגיל 1 - עבודה עם dmesg¶
א. הריצו את הפקודות הבאות ותעדו את התוצאות:
# צפייה ב-kernel log:
dmesg | tail -30
# סינון לפי רמת חשיבות (שגיאות בלבד):
dmesg --level=err
# אזהרות ומעלה:
dmesg --level=warn,err,crit,alert,emerg
# עם timestamps קריאים:
dmesg -T | tail -20
ב. אם יש לכם מודול קרנל (או השתמשו ב-modprobe של מודול קיים), בצעו:
מה מופיע בלוג?
ג. חפשו הודעות שגיאה או אזהרה ב-dmesg. מצאו לפחות הודעה אחת והסבירו מה היא אומרת.
תרגיל 2 - קריאת kernel oops¶
קראו את הודעת ה-oops הבאה וענו על השאלות:
BUG: unable to handle page fault for address: 0000000000000010
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
Oops: 0000 [#1] SMP NOPTI
CPU: 1 PID: 3456 Comm: test_program Tainted: G O 5.15.0 #1
RIP: 0010:linked_list_search+0x1e/0x60 [my_module]
Code: 55 48 89 e5 48 8b 07 48 85 c0 74 1a 48 8b 50 10 39 f2 74 18 ...
RSP: 0018:ffffc90001234abc EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff888100567000 RCX: 0000000000000042
RDX: 0000000000000000 RSI: 0000000000000042 RDI: ffff888100890000
RBP: ffffc90001234ac0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ffff888100890000
R13: 0000000000000042 R14: 0000000000000000 R15: 0000000000000000
FS: 00007f1234567000(0000) GS:ffff88813bc00000(0000)
Call Trace:
<TASK>
device_ioctl+0x85/0x120 [my_module]
__x64_sys_ioctl+0x91/0xc0
do_syscall_64+0x3b/0x90
entry_SYSCALL_64_after_hwframe+0x44/0xae
</TASK>
א. באיזו פונקציה קרתה השגיאה? באיזה מודול?
ב. מה הכתובת שגרמה ל-page fault? מה זה כנראה אומר?
ג. מה ערך RAX? מה הקשר לכתובת שגרמה ל-fault?
ד. מה ה-call trace מגלה על הזרימה? מאיפה הגיעה הקריאה?
ה. שחזרו: מה כנראה הקוד הבעייתי? (רמז: linked list, RAX=0, כתובת 0x10)
תרגיל 3 - Ftrace¶
בצעו את התרגילים הבאים על מכונת לינוקס (VM מומלצת):
א. מעקב אחרי syscalls של פקודה ספציפית:
# הפעילו function tracer:
echo function > /sys/kernel/debug/tracing/current_tracer
# הגבילו לפונקציות של open:
echo 'do_sys_openat2' > /sys/kernel/debug/tracing/set_ftrace_filter
# הפעילו:
echo 1 > /sys/kernel/debug/tracing/tracing_on
# הריצו פקודה:
ls /tmp
# קראו את התוצאות:
cat /sys/kernel/debug/tracing/trace
# כבו:
echo 0 > /sys/kernel/debug/tracing/tracing_on
echo nop > /sys/kernel/debug/tracing/current_tracer
כמה פעמים נקראה do_sys_openat2? מה ls פותח?
ב. השתמשו ב-function_graph tracer:
echo function_graph > /sys/kernel/debug/tracing/current_tracer
echo 'do_sys_openat2' > /sys/kernel/debug/tracing/set_graph_function
echo 1 > /sys/kernel/debug/tracing/tracing_on
cat /etc/hostname
echo 0 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace
ציירו את עץ הקריאות שאתם רואים. כמה זמן לקח לפתוח את הקובץ?
תרגיל 4 - perf¶
א. פרופיילינג בסיסי:
הריצו תוכנית שצורכת CPU (למשל stress --cpu 1 --timeout 5 או dd if=/dev/urandom of=/dev/null bs=1M count=100):
אילו פונקציות צורכות הכי הרבה CPU?
ב. ספירת אירועי חומרה:
sudo perf stat -e cycles,instructions,cache-references,cache-misses,branch-instructions,branch-misses ls -la /usr/bin/
מהו IPC (Instructions Per Cycle)? האם יש הרבה cache misses?
ג. מעקב אחרי syscalls:
אילו syscalls curl עושה הכי הרבה? כמה זמן הוא מבלה בכל syscall?
תרגיל 5 - bpftrace¶
הערה: תרגיל זה דורש bpftrace מותקן (sudo apt install bpftrace או שווה ערך).
א. כתבו one-liner ב-bpftrace שמדפיס את שם התהליך וה-PID בכל פעם שתהליך חדש נוצר:
ב. כתבו one-liner שמראה היסטוגרמה של גדלי read() syscalls:
ג. כתבו one-liner שסופר כמה פעמים כל syscall נקרא, ומציג את הסטטיסטיקה כש-Ctrl+C נלחץ:
ד. (בונוס) כתבו one-liner שמציג את ה-latency (בזמן) של כל write() syscall, מקובץ לפי תהליך: