לדלג לתוכן

דיבוג קרנל - תרגול

תרגיל 1 - עבודה עם dmesg

א. הריצו את הפקודות הבאות ותעדו את התוצאות:

# צפייה ב-kernel log:
dmesg | tail -30

# סינון לפי רמת חשיבות (שגיאות בלבד):
dmesg --level=err

# אזהרות ומעלה:
dmesg --level=warn,err,crit,alert,emerg

# עם timestamps קריאים:
dmesg -T | tail -20

ב. אם יש לכם מודול קרנל (או השתמשו ב-modprobe של מודול קיים), בצעו:

sudo modprobe dummy   # או כל מודול אחר
dmesg | tail -5

מה מופיע בלוג?

ג. חפשו הודעות שגיאה או אזהרה ב-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):

sudo perf record -g -p $(pgrep stress) sleep 3
sudo perf report

אילו פונקציות צורכות הכי הרבה 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:

sudo perf trace -s curl https://example.com 2>&1 | tail -20

אילו syscalls curl עושה הכי הרבה? כמה זמן הוא מבלה בכל syscall?


תרגיל 5 - bpftrace

הערה: תרגיל זה דורש bpftrace מותקן (sudo apt install bpftrace או שווה ערך).

א. כתבו one-liner ב-bpftrace שמדפיס את שם התהליך וה-PID בכל פעם שתהליך חדש נוצר:

sudo bpftrace -e 'tracepoint:sched:sched_process_exec { ... }'

ב. כתבו one-liner שמראה היסטוגרמה של גדלי read() syscalls:

sudo bpftrace -e 'tracepoint:syscalls:sys_exit_read /args->ret > 0/ { ... }'

ג. כתבו one-liner שסופר כמה פעמים כל syscall נקרא, ומציג את הסטטיסטיקה כש-Ctrl+C נלחץ:

sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { ... }'

ד. (בונוס) כתבו one-liner שמציג את ה-latency (בזמן) של כל write() syscall, מקובץ לפי תהליך:

# רמז: השתמשו ב-nsecs ובהיסטוגרמה