Tracing và debug Linux kernel¶
Debug kernel khác debug ứng dụng ở chỗ kernel không có debugger bên ngoài tiến trình: khi kernel dừng thì cả hệ thống dừng, và khi kernel lỗi thì thường không còn công cụ nào chạy để quan sát. Vì vậy kernel có nhiều nhóm công cụ, mỗi nhóm phù hợp một giai đoạn của quá trình tìm lỗi. Trang này trình bày cách phân nhóm các công cụ, so sánh các nhóm theo mức can thiệp vào hệ thống, hướng dẫn chọn công cụ theo triệu chứng, rồi liệt kê các cấu hình kernel cần có sẵn trước khi debug. Chi tiết từng công cụ nằm ở các trang con.
Phân nhóm công cụ¶
Các công cụ được chia theo câu hỏi mà chúng trả lời, từ nhẹ nhất đến nặng nhất.
| Nhóm | Câu hỏi trả lời | Công cụ | Trang |
|---|---|---|---|
| Log | Kernel đang báo gì | printk, dmesg, dynamic debug |
printk và kernel log, Dynamic Debug |
| Tracing | Kernel đang làm gì, theo thứ tự nào, mất bao lâu | ftrace, kprobe, uprobe, tracepoint | FTrace, Tracepoint và trace events |
| Chẩn đoán lỗi | Lỗi xảy ra ở dòng code nào | Oops, call trace, bộ phát hiện lỗi (KASAN, lockdep, kmemleak) | Đọc Oops và Panic |
| Live debug | Trạng thái biến và thanh ghi tại thời điểm dừng | KGDB, kdb, JTAG | KGDB và kdb, JTAG Debug |
| Post-mortem | Trạng thái hệ thống ngay trước khi chết | kdump, pstore và ramoops | Kernel Crash Dump (kdump) |
Ba nhóm đầu hoạt động khi kernel còn chạy bình thường và có thể dùng trên hệ thống đang vận hành. Live debug cần dừng kernel hoặc dừng CPU. Post-mortem chỉ có tác dụng sau khi lỗi đã xảy ra, nên phải cấu hình từ trước.
So sánh theo mức can thiệp¶
| Tiêu chí | Log | Tracing | Live debug bằng KGDB | Live debug bằng JTAG | Post-mortem |
|---|---|---|---|---|---|
| Dừng được kernel | Không | Không | Có | Có | Không áp dụng |
| Cần phần cứng thêm | Không | Không | Cổng serial hoặc mạng | Bộ JTAG và kết nối tới SoC | Vùng RAM dành riêng hoặc vùng lưu trữ |
| Dùng được khi kernel treo cứng | Không | Không | Chỉ khi vẫn vào được debugger | Có | Có, nếu có cơ chế kích hoạt panic |
| Ảnh hưởng thời gian chạy | Thấp đến trung bình, tùy lượng log | Thấp khi tắt, tăng theo số event bật | Nặng, hệ thống dừng khi vào debugger | Nặng, CPU dừng khi gặp breakpoint | Không ảnh hưởng khi chạy bình thường |
| Phù hợp với lỗi timing | Thấp | Cao | Thấp | Thấp | Không áp dụng |
Các mức "thấp", "cao" ở bảng là so sánh tương đối giữa các nhóm, không phải số đo. Mức ảnh hưởng thực tế phụ thuộc cấu hình và khối lượng event, nên cần đo lại trên hệ thống cụ thể trước khi dùng trong môi trường sản phẩm.
Chọn công cụ theo triệu chứng¶
| Triệu chứng | Bắt đầu bằng | Bước tiếp theo |
|---|---|---|
| Driver không probe hoặc probe lỗi, chưa rõ nguyên nhân | Dynamic debug cho driver đó, đọc log bằng dmesg | FTrace với function tracer để xem luồng gọi |
| Kernel in oops hoặc panic | Đọc Oops và Panic để giải mã call trace | Bật bộ phát hiện lỗi nếu lỗi là hỏng bộ nhớ |
| Hệ thống treo, không in gì | Bật watchdog và kdump để biến trạng thái treo thành panic | JTAG nếu kernel không còn phản hồi |
| Cần biết hàm nào chiếm nhiều thời gian | FTrace với function_graph hoặc perf |
Giới hạn bộ lọc về hàm nghi ngờ |
| Cần xem giá trị biến tại một điểm mà không sửa code | Kprobe qua ftrace | KGDB nếu cần dừng và xem nhiều biến |
| Cần step từng dòng trong kernel | KGDB trên QEMU để làm quen | KGDB trên board qua serial, hoặc JTAG |
| Lỗi chỉ xuất hiện trên thiết bị ngoài hiện trường | Cấu hình pstore, ramoops và kdump từ trước | Phân tích dump hoặc log thu được |
| Lỗi xảy ra rất sớm khi boot, chưa có console | earlycon và initcall_debug, xem Log boot |
JTAG |
Với phần lớn lỗi, thứ tự hợp lý là đi từ nhóm nhẹ đến nhóm nặng: đọc log, rồi trace để thu hẹp vùng nghi ngờ, rồi mới dùng live debug trên đoạn code đã xác định.
flowchart TD
A[Có lỗi trên kernel] --> B{Kernel còn chạy}
B -- Có --> C{Đã biết vùng code nghi ngờ}
C -- Chưa --> D[Log và tracing để thu hẹp vùng]
C -- Rồi --> E[Live debug hoặc kprobe trên vùng đó]
B -- Không, có oops hoặc panic --> F[Đọc oops, giải mã call trace]
B -- Không, treo không log --> G[kdump, watchdog hoặc JTAG]
F --> H{Đủ dữ kiện}
H -- Chưa --> I[kdump và phân tích bằng crash]
Cấu hình kernel cần có sẵn¶
Phần lớn công cụ trên yêu cầu bật cấu hình khi build kernel. Nếu thiếu thì phải build lại, nên cần quyết định trước khi triển khai.
| Cấu hình | Dùng cho |
|---|---|
CONFIG_DEBUG_INFO |
Thông tin debug trong vmlinux, cần cho gdb, crash và giải mã địa chỉ về dòng code |
CONFIG_KALLSYMS |
Tên symbol trong call trace và trong ftrace |
CONFIG_DEBUG_FS |
Giao diện debugfs, nơi nhiều công cụ tạo file điều khiển |
CONFIG_FTRACE và các tracer con |
ftrace, xem FTrace |
CONFIG_DYNAMIC_DEBUG |
Dynamic debug, xem Dynamic Debug |
CONFIG_KGDB |
KGDB và kdb, xem KGDB và kdb |
CONFIG_CRASH_DUMP |
Cơ chế kdump, xem Kernel Crash Dump (kdump) |
Danh sách đầy đủ và các tùy chọn đi kèm nằm ở từng trang con tương ứng.
Các trang có hậu tố (WIP) trong nav đã có chỗ đứng nhưng chưa có nội dung: eBPF và bpftrace, perf trong kernel, Đo độ trễ bằng tracing, Bộ phát hiện lỗi bộ nhớ và đồng bộ, Debug bộ nhớ kernel, Fault injection, debugfs và truy cập thanh ghi.
Liên quan¶
- Tracepoint và trace events: hook tĩnh, bật và lọc event,
trace-cmd. - printk và kernel log: ghi log trong code kernel và đọc lại qua
dmesg,/dev/kmsg. - Debug ứng dụng user space: gdbserver, core dump và strace trên board.
- Perf: công cụ profiling dùng chung cho user space và kernel.
- Serial console: kênh log và kênh vào debugger khi chưa có mạng.
- Log boot và earlycon: quan sát giai đoạn boot.
- Kernel Command Line: các tham số như
loglevel,earlycon,initcall_debug. - Real-time Linux (PREEMPT_RT): đo độ trễ của kernel real-time.