Linux驱动-内核调试手段
以下代码示例都是以Linux开源社区代码为示例,其他版本可能存在差异,版本信息如下:
tag : v6.6.64
commit : 22a054ea1f081d7837cc8e24ad4c7aa36e8bba04
URL : https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tag/?h=v6.6.64
打印与日志
这是最基础且常用的手段。
printk:内核最经典的打印函数。通过设置不同的日志级别(如KERN_ERR、KERN_INFO),可以控制输出。配合启动参数loglevel=8可查看全部信息。dev_dbg/pr_debug:动态调试的核心。只有在定义了DEBUG宏或通过动态调试框架开启后才会输出,适合精细控制打印量。no_printk:用于保留调试语句的格式检查,但编译后不产生实际输出,避免性能损耗。
内核日志
功能配置
配合启动参数 loglevel=8 可查看全部信息。
使用 dmesg 命令查看内核环形缓冲区,或通过 tail -f /var/log/kern.log 实时监控。
动态调试
功能配置
CONFIG_DYNAMIC_DEBUG 动态调试总开关
调整日志等级
DEBUG_KERNEL 内核调试总开关
CONSOLE_LOGLEVEL_DEFAULT 控制台打印等级
CONSOLE_LOGLEVEL_QUIET 安静模式(quiet),控制台打印等级
MESSAGE_LOGLEVEL_DEFAULT 指定未标明等级printk的日志等级
或启动参数增加loglevel=8
使用 dmesg 命令查看内核环形缓冲区
核心模块列表
查看模块名称:ls /sys/module
| 块 | 作用 | 典型日志内容 |
|---|---|---|
usbcore | USB核心层 | 设备枚举、配置、电源管理、URB提交/完成 |
xhci_hcd | USB 3.0主机控制器 | XHCI协议事件、端口状态变化、TRB(传输请求块)处理 |
ehci_hcd | USB 2.0主机控制器 | EHCI调度、QH/TD(队列头/传输描述符)操作 |
uhci_hcd 或 ohci_hcd | USB 1.1主机控制器 | 低速/全速设备控制 |
hub | USB集线器驱动 | 端口连接/断开事件、电源管理 |
usb-storage | USB存储设备驱动 | SCSI命令转换、批量传输日志 |
hid | HID设备(如键盘鼠标) | HID报告描述符解析、中断传输 |
全局开启USB核心调试1
2
3
4启用usbcore所有调试信息
echo "module usbcore +p" > /sys/kernel/debug/dynamic_debug/control
启用Hub事件日志
echo "module hub +p" > /sys/kernel/debug/dynamic_debug/control
开启SCSI相关(调试存储设备会涉及)调试1
2
3
4启用 scsi_mod 的调试(SCSI 核心层)
echo 'module scsi_mod +p' > /sys/kernel/debug/dynamic_debug/control
启用 sd_mod 的调试(SCSI 磁盘驱动)
echo 'module sd_mod +p' > /sys/kernel/debug/dynamic_debug/control
按需开启主机控制器驱动1
2
3根据实际使用的控制器选择(通过lsusb -t查看)
echo "module xhci_hcd +p" > /sys/kernel/debug/dynamic_debug/control # USB 3.0
echo "module ehci_hcd +p" > /sys/kernel/debug/dynamic_debug/control # USB 2.0
设备驱动调试1
2
3
4
5例如调试USB存储设备
echo "module usb-storage +p" > /sys/kernel/debug/dynamic_debug/control
调试HID设备
echo "module hid +p" > /sys/kernel/debug/dynamic_debug/control
echo "module hid_generic +p" > /sys/kernel/debug/dynamic_debug/control
按文件过滤1
2
3
4
5
6
7
8# 打开特定文件
echo file drivers/usb/core/hub.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/usb/core/hcd.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/usb/dwc3/dwc3-*.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/scsi/sd.c +p > /sys/kernel/debug/dynamic_debug/control
# 仅打印xhci_hcd中关于端口状态的日志
echo "file drivers/usb/host/xhci*.c line 1000-2000 +p" > /sys/kernel/debug/dynamic_debug/control
使用示例:打开usb文件日志——hub、hcd、dwc3和sd
开启模块调试1
2
3
4
5
6
7
8
9
10
11
12
13启用usbcore所有调试信息
echo "module usbcore +p" > /sys/kernel/debug/dynamic_debug/control
启用Hub事件日志
echo "module hub +p" > /sys/kernel/debug/dynamic_debug/control
启用 scsi_mod 的调试(SCSI 核心层)
echo 'module scsi_mod +p' > /sys/kernel/debug/dynamic_debug/control
启用 sd_mod 的调试(SCSI 磁盘驱动)
echo 'module sd_mod +p' > /sys/kernel/debug/dynamic_debug/control
根据实际使用的控制器选择(通过lsusb -t查看)
echo "module xhci_hcd +p" > /sys/kernel/debug/dynamic_debug/control # USB 3.0
例如调试USB存储设备
echo "module usb-storage +p" > /sys/kernel/debug/dynamic_debug/control
开启文件1
2
3
4echo file drivers/usb/core/hub.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/usb/core/hcd.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/usb/dwc3/dwc3-*.c +p > /sys/kernel/debug/dynamic_debug/control
echo file drivers/scsi/sd.c +p > /sys/kernel/debug/dynamic_debug/control
主控注册
1 | [root@tst ] |
设备接入
1 | [ 5722.347763][ C0] xhci-hcd xhci-hcd.0.auto: Port change event, 2-1, id 2, portsc: 0xa021603 |
读写数据
1 | [root@tst ]# dd if=/dev/urandom of=/dev/sda bs=1K count=8K |
移除SCSI缓存
1 | [root@tst ]# echo 1 > /sys/class/block/sda/device/delete |
安全弹出
1 | [root@tst ] |
设备拔出
1 | [ 981.667755][ C0] xhci-hcd xhci-hcd.0.auto: Port change event, 2-1, id 2, portsc: 0xc0202a0 |
文件系统接口
- procfs:通常用于展示进程或系统全局信息。驱动常在此创建只读文件,方便快速查看内部状态。
- sysfs:内核推荐的属性接口,位于
/sys/。既是调试工具,也是驱动与用户空间的标准配置接口,支持读写。 - debugfs:专门为开发者设计的接口,位于
/sys/kernel/debug/。不应用于生产功能,适合存放驱动内部状态、寄存器快照等调试信息。
sysfs
功能配置
1 | static struct device_attribute dev_attr_xx_read = __ATTR_WO(xx_read); |
使用示例:usb驱动
1 | [root@tst ]# ls /sys/class/udc/ |
debugfs
功能配置
参考linux-6.6.64/drivers/usb/dwc3/debugfs.c1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GSBUSCFG0), // {&"GSBUSCFG0"[0], 0xc100}
dump_register(GSBUSCFG1), // {&"GSBUSCFG1"[0], 0xc104}
...
}
static const struct file_operations dwc3_lsp_fops = {
.open = dwc3_lsp_open,
.write = dwc3_lsp_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void dwc3_debugfs_init(struct dwc3 *dwc)
{
dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL);
dwc->regset->regs = dwc3_regs;
dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
dwc->regset->dev = dwc->dev;
root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root);
debugfs_create_regset32("regdump", 0444, root, dwc->regset);
debugfs_create_file("lsp_dump", 0644, root, dwc, &dwc3_lsp_fops);
}
使用示例:访问usb驱动属性
查看是否挂载debugfs1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 查看是否挂载debugfs
$ mount | grep debugfs
# 手动挂载debugfs
$ mount -t debugfs none /sys/kernel/debug
$ ls /sys/kernel/debug/dwc3/<controller>/<endpoint>
tx_fifo_size
rx_fifo_size
tx_request_queue
rx_request_queue
rx_info_queue
descriptor_fetch_queue
event_queue
transfer_type
trb_ring
GDBGEPINFO
使用示例:增加驱动显示trb缓存
linux-6.6.64/drivers/usb/dwc3/debugfs.c加入桩节点:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index ebf03468f..b8933e16f 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
static const struct dwc3_ep_file_map dwc3_ep_file_map[] = {
{ "GDBGEPINFO", &dwc3_ep_info_register_fops, },
};
+static void (*dwc3_debug_hook)(struct seq_file *s);
+static ssize_t (*dwc3_debug_write_hook)(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos);
+static int trb_ring_buffer_show(struct seq_file *s, void *unused)
+{
+ seq_puts(s, "trb_ring_buffer: default simple output\n");
+
+ /* 如果模块已注册 hook,则调用模块提供的函数 */
+ if (dwc3_debug_hook)
+ dwc3_debug_hook(s);
+
+ return 0;
+}
+
+static int trb_ring_buffer_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, trb_ring_buffer_show, NULL);
+}
+
+static ssize_t trb_ring_buffer_write(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ if (dwc3_debug_write_hook)
+ return dwc3_debug_write_hook(file, buf, len, ppos);
+
+ return len; // 默认忽略写
+}
+static DEFINE_MUTEX(trb_lock);
+static const struct file_operations dwc3_ep_trb_ring_buffer_fops = {
+ .owner = THIS_MODULE,
+ .open = trb_ring_buffer_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = trb_ring_buffer_write,
+};
+void register_dwc3_debug_hook(void (*show)(struct seq_file *),
+ ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *))
+{
+ mutex_lock(&trb_lock);
+ dwc3_debug_hook = show;
+ dwc3_debug_write_hook = write;
+ mutex_unlock(&trb_lock);
+}
+EXPORT_SYMBOL(register_dwc3_debug_hook);
+
+
void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
{
struct dentry *dir;
void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
debugfs_create_file(name, 0444, dir, dep, fops);
}
+
+ debugfs_create_file("trb_ring_buffer", 0444, dir, dep, &dwc3_ep_trb_ring_buffer_fops);
}
void dwc3_debugfs_remove_endpoint_dir(struct dwc3_ep *dep)
dwc3_trb_buffer_debug.c模块文件内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78// 文件: dwc3_debug.c
/* 模拟 TRB buffer 数据结构 */
struct dwc3_ep {
char name[16];
unsigned num_trbs;
u32 trb_pool[MAX_TRB][4]; // 每个 TRB 16 bytes
};
/* 调试配置 */
// static int dump_ep_list[MAX_EP];
static int dump_size = 16; // 每 TRB 默认打印 16 bytes
/* hook 回调实现 */
static void dwc3_debug_show(struct seq_file *s)
{
struct dwc3_ep ep = { "ep1", 4 }; // 模拟 EP
int i, j;
seq_printf(s, "Module TRB dump for EP %s\n", ep.name);
for (i = 0; i < ep.num_trbs; i++) {
seq_printf(s, "TRB[%d]: ", i);
for (j = 0; j < dump_size / 4; j++)
seq_printf(s, "%08x ", ep.trb_pool[i][j]);
seq_puts(s, "\n");
}
}
static ssize_t dwc3_debug_write(struct file *file,
const char __user *buf,
size_t len, loff_t *ppos)
{
char cmd[64];
if (len >= sizeof(cmd))
return -EINVAL;
if (copy_from_user(cmd, buf, len))
return -EFAULT;
cmd[len] = 0;
// 简单解析数字配置 TRB 打印大小
// kstrtoint(cmd, 0, &dump_size);
// kstrtoul(cmd, 0, &dump_size)
pr_info("dwc3_debug: dump_size set to %d\n", dump_size);
return len;
}
/* 模块初始化注册 hook */
static int __init dwc3_debug_init(void)
{
extern void register_dwc3_debug_hook(void (*show)(struct seq_file *),
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *));
register_dwc3_debug_hook(dwc3_debug_show, dwc3_debug_write);
pr_info("dwc3_debug: module loaded\n");
return 0;
}
static void __exit dwc3_debug_exit(void)
{
pr_info("dwc3_debug: module unloaded\n");
}
module_init(dwc3_debug_init);
module_exit(dwc3_debug_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Generated Example");
MODULE_DESCRIPTION("dwc3 debug module for TRB buffer");
Makefile内容:1
2
3
4
5
6
7
8
9
10
11
12
13KDIR ?= ../linux-6.6.64
KOUT ?= ../linux-6.6.64/build
CROSS_COMPILETOOL ?= aarch64-linux-gnu-
PWD := $(shell pwd)
obj-m := dwc3_trb_debug.o
all:
$(MAKE) CROSS_COMPILE=$(CROSS_COMPILETOOL) ARCH=arm64 -C $(KDIR) O=$(KOUT) M=$(PWD) modules
clean:
$(MAKE) CROSS_COMPILE=$(CROSS_COMPILETOOL) ARCH=arm64 -C $(KDIR) O=$(KOUT) M=$(PWD) clean
使用示例1
2echo "all all 256" > trb_ring_buffer
echo "1,3 normal,link 512" > trb_ring_buffer
追踪与剖析
- Ftrace:内核内置的追踪器。可用于查看函数调用流程、分析延时。常用
function_graph跟踪器查看驱动函数的调用栈,或使用trace_printk在追踪日志中加入自定义信息,其性能通常优于printk。 - Perf:主要用于性能分析,可以定位驱动中的CPU占用过高、缓存命中率低等问题。
- eBPF:现代Linux的高性能调试利器。可在不修改内核代码的情况下,挂载kprobe/uprobe追踪驱动函数,安全性高且性能开销极小。
FTrace
功能配置
配置内核参数,依赖CONFIG_DEBUG_FS功能1
2
3
4
5
6
7
8
9./make.sh menuconfig
Kernel hacking > Tracers
-*- Kernel Function Tracer
[*] Kernel Function Graph Tracer (NEW)
[*] Kernel Function Graph Return Value
-*- enable/disable function tracing dynamically
[*] Kernel function profiler
[*] Trace max stack
ftrace的控制接口位于/sys/kernel/debug/tracing
或者手动挂载/sys/kernel/tracing1
mount -t tracefs nodev /sys/kernel/tracing
基本使用方式1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38# 查看支持的追踪器 function_graph function
cat available_tracers
# 设置追踪器为函数图
echo function_graph > current_tracer
# 设置要追踪的根函数(支持通配符)
echo dwc3* > set_graph_function
# 设置追踪函数
echo xhci_* >> set_ftrace_filter
# 设置函数过滤器
echo _dev_info >> set_ftrace_notrace
echo mutex* >> set_ftrace_notrace
# 开启追踪
echo 1 > tracing_on
# 等待一段时间后停止
echo 0 > tracing_on
# 查看结果
cat trace | head -n 50
# 隐藏函数执行时间 (去掉 280.765 us 这种干扰)
echo nosleep-time > trace_options
echo nograph-time > trace_options
# 隐藏 CPU 编号 (去掉 7) 这种列)
echo nocpu-vis-graph > trace_options
# 隐藏中断/上下文标志 (去掉 ! 或 + 等符号)
echo noirq-info > trace_options
# 如果不需要查看每行的绝对时间戳
echo noannotate > trace_options
# 设置最大层次
echo 5 > max_graph_depth
Trace Events
使用示例:追踪usb
假设要跟踪 进程创建 和 进程退出 事件,它们都包含 pid 和 comm(进程名)字段,可以使用 DECLARE_EVENT_CLASS 复用代码:
定义事件类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 基本用法
DECLARE_EVENT_CLASS(
name, // 事件类名称
TP_PROTO(arguments), // 事件的原型 (参数列表)
TP_ARGS(arguments), // 事件的参数
TP_STRUCT__entry(...), // 结构体字段定义
TP_fast_assign(...), // 事件字段的赋值
TP_printk(fmt, ...) // 事件的格式化打印
);
// 示例
DECLARE_EVENT_CLASS(
process_event,
TP_PROTO(pid_t pid, const char *comm),
TP_ARGS(pid, comm),
TP_STRUCT__entry(
__field(pid_t, pid)
__string(comm, comm)
),
TP_fast_assign(
__entry->pid = pid;
__assign_str(comm, comm);
),
TP_printk("pid=%d comm=%s", __entry->pid, __get_str(comm))
);
定义 fork 和 exit 事件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 基本用法
DEFINE_EVENT(
name, // 事件类名称(与 DECLARE_EVENT_CLASS 一致)
event_name, // 具体事件的名称
TP_PROTO(...),
TP_ARGS(...)
);
// 示例
DEFINE_EVENT(process_event,
process_fork,
TP_PROTO(pid_t pid, const char *comm),
TP_ARGS(pid, comm));
DEFINE_EVENT(process_event,
process_exit,
TP_PROTO(pid_t pid, const char *comm),
TP_ARGS(pid, comm));
代码中触发事件1
2
3
4
5// 基本用法
trace_EVENTNAME(...)
// 示例
trace_process_fork(current->pid, current->comm);
trace_process_exit(current->pid, current->comm);
这样就可以高效地记录进程 fork 和退出的事件,而不用重复定义 TP_STRUCT__entry、TP_fast_assign 和 TP_printk。
tracepoints
使用示例:追踪usb
查看功能是否开启1
2
3ls /sys/kernel/debug/tracing
mount -t tracefs nodev /sys/kernel/tracing
mount -t debugfs none /sys/kernel/debug
查看trace支持的event1
2
3grep "^usb:" /sys/kernel/debug/tracing/available_events
grep "^xhci" /sys/kernel/debug/tracing/available_events
grep "^dwc3" /sys/kernel/debug/tracing/available_events
配置trace的event1
2
3
4
5
6# 开启某个trace
echo 1 > /sys/kernel/debug/tracing/events/usb/usb_submit_urb/enable
echo 1 > /sys/kernel/debug/tracing/events/usb/usb_complete_urb/enable
# 开启模块trace
echo 1 > /sys/kernel/debug/tracing/events/dwc3/enable
echo 1 > /sys/kernel/debug/tracing/events/xhci/enable
查看trace1
2
3
4# 查看trace
cat /sys/kernel/debug/tracing/trace
# 实时trace
cat /sys/kernel/debug/tracing/trace_pipe
trace写文件1
2
3
4
5
6
7echo > /sys/kernel/debug/tracing/trace
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 配置trace的event
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 在这里进行你的 USB 操作(插拔、传输等)
echo 0 > /sys/kernel/debug/tracing/tracing_on
cp /sys/kernel/debug/tracing/trace usb_trace.log
内核崩溃分析
- Kdump:系统崩溃(如内核态空指针访问)时,
Kdump会捕获并保存内存转储文件(vmcore)。 - 分析工具:结合 Crash 工具进行分析,可查看崩溃时的全局变量、调用栈、内存数据。在开发阶段,也可使用
BUG_ON、WARN_ON等断言宏来主动预警。
静态检查
在运行前排查潜在问题。
- Sparse:专门用于检查内核代码的端序问题(如
__bitwise)和地址空间类型(如__user)。 - Smatch / Coccinelle:分别用于检查空指针、资源泄漏等逻辑错误,以及进行语义匹配和自动修改。
- 编译器警告:建议使用
Wall、Werror以及内核推荐的W=1编译参数,尽可能消除警告。
硬件辅助调试
- JTAG:使用仿真器(如BDI3000、ULINK)进行源码级单步调试、设置硬件断点。在调试早期启动代码或DMA(直接内存访问)导致的“内存被谁改写”问题时,效果显著。
- 逻辑分析仪 / 示波器:用于排查硬件时序、总线协议(I2C、SPI)是否正确,可确认数据是否真正被硬件发送出去。
JTAG
调试模式内核编译
主要参考:QEMU调试Linux内核环境搭建1
./make.sh menuconfig
在配置菜单中,启用内核debug,关闭地址随机化,不然断点处无法停止。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 6.1.64版本内核选项
# 优化选项需要直接从顶层Makefile修改即可
# General setup --->
# Compiler optimization level (Optimize for size (-Os)) --->
# (X) Optimize for size (-Os)
Kernel Features --->
[] Randomize the address of the kernel image
Kernel hacking --->
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Provide GDB scripts for kernel debuggin
[*] Make section mismatch errors non-fatal
# 4.14.191
# 需要关闭优化项 Compiler optimization level (Optimize for size (-Os))
Kernel hacking --->
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debuggin
Processor type and features ---->
[] Randomize the address of the kernel image (KASLR)
调整全局优化等级
强行修改优化选项改为-Og(-O0 可以完全禁用优化,但生成的代码体积有点大)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16diff --git a/Makefile b/Makefile
index c809b21c3..7b189d210 100644
--- a/Makefile
+++ b/Makefile
KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
-KBUILD_CFLAGS += -O2
+KBUILD_CFLAGS += -Og
KBUILD_RUSTFLAGS += -Copt-level=2
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS += -Os
+KBUILD_CFLAGS += -Og
KBUILD_RUSTFLAGS += -Copt-level=s
endif
校验是否将static函数优化掉1
2// hub_port_connect_change在android-kernel-6.1/drivers/usb/core/hub.c中的static函数,默认不应该内联
nm build/vmlinux | grep "hub_port_connect_change"
使用混合编译方式编译内核,否则部分模块会报错1
./make.sh CFLAGS_patching.o="-O2" CFLAGS_pci.o="-O2" -j8
调整模块级优化等级
这里调整usb模块的优化等级,全局依然保持(-O2)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 1e7868497..0e9875a29 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
# SPDX-License-Identifier: GPL-2.0
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
+# 模块使用指定优化等级
+ccflags-y += -Og -g
+# core.o使用指定优化等级
+# CFLAGS_core.o := -Og -g
dwc3-y := core.o
ifneq ($(CONFIG_TRACING),)
启动OpenOCD
【不可用】wsl中启动(USB无法绑定)
wsl中使用OpenOCD需要将JTAG设备连接到子系统中,管理员权限运行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$ usbipd list
Connected:
BUSID VID:PID DEVICE STATE
2-1 1fc9:5601 USB 串行设备 (COM18), USB 输入设备 Not shared
2-8 0483:5130 USB 输入设备 Not shared
2-9 0a12:0001 Generic Bluetooth Radio Not shared
2-13 5000:0220 USB 输入设备 Not shared
3-1 04e2:1414 XR21V1414 USB UART Ch A (COM7), XR21V1414 USB UART Ch B (... Not shared
Persisted:
GUID DEVICE
3d92583e-5954-49b4-8cc0-881a70c3d5de XR21V1414 USB UART Ch A (COM20), XR21V1414 USB UART Ch B ...M
96fd4531-5c1f-432e-be0a-b9cde47306fa J-Link
$ usbipd bind --force --busid 2-1
$ usbipd attach --wsl --auto-attach --busid 2-1
windows中启动
暂时无法在飞书文档外展示此内容
容器中访问主机,需要暴露调试端口3333,并增加绑定网络
允许端口通过防火墙,确保外部请求可达:
- 打开 设置 > 搜索 “Windows Defender 防火墙”。
- 点击 高级设置 进入高级安全防火墙。
- 在左侧选择 入站规则 > 右侧点击 新建规则。
- 规则类型选择 端口 > 点击 下一步。
- 选择 TCP,输入特定端口
3333> 点击 下一步。 - 选择 允许连接 > 点击 下一步。
- 勾选所有网络类型(域、专用、公用)> 点击 下一步。
- 输入规则名称(如
openocd-调试端口)> 点击 完成。
openocd-dap.cfg1
2
3
4adapter driver cmsis-dap
transport select jtag
adapter speed 12000
bindto 0.0.0.0
windows终端启动OpenOCD1
$ .\bin\openocd -c "set _CORES [range 0 8]" -c "set _DEF_RTOS linux" -f .\openocd\scripts\interface\cmsis-dap.cfg -f .\openocd\scripts\target\cpu-a78.cfg
windows终端中查看绑定的端口1
2$ netstat -ano | findstr :3333
TCP 0.0.0.0:3333 0.0.0.0:0 LISTENING 25976
启动GDB开启远程调试
容器中启动1
2aarch64-linux-gnu-gdb kernel/android-kernel-6.1/build/vmlinux
target remote 10.28.11.217:3333
使用.gdbinit文件可以避免重复输入1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17define add_user_break
hb *$arg0
commands
printf "hit breakpoint, pc:%#lx id:%d\n", $pc, $_hit_bpnum
continue
end
end
target extended-remote :3333
d
add_user_break 0xffff800080946ec8
add_user_break 0xffff800080946f84
add_user_break 0xffff800080946fb4
add_user_break 0xffff800080946fec
add_user_break 0xffff80008094700c
add_user_break 0xffff80008094701c
c
驱动专用手段
USB Monitor
usbmon是内核监控工具,需要手动开启(或修改宏CONFIG_USB_MON)1
2
3
4
5
6
7
8
9make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build menuconfig
Device Drivers --->
[*] USB support --->
<M> USB Monitor
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build -j8
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build modules -j8
usbmon模块存在路径 build/drivers/usb/mon/usbmon.ko
将模块上传板端并加载1
2
3adb push .\build\drivers\usb\mon\usbmon.ko /home/root
insmod ./usbmon.ko
modprobe usbmon # 自动解决依赖,但需要模块文件在/lib/modules/6.1.64/kernel中
查看统计信息,0u表示所有USB总线,1
2
3mount -t debugfs none_debugs /sys/kernel/debug # 挂载调试文件系统
root@tst:~# ls /sys/kernel/debug/usb/usbmon
0s 0u 1s 1t 1u 2s 2t 2u
usbmon.rst官方说明文档
usbmon数据结构说明
1 | # 直接抓取所有总线数据 |
Event:
- S:submission
- C:callback
- E:submission error
“Address”结构:URB type & direction:Bus number:Device address:Endpoint number
URB type & direction:
- Ci Co Control input and output
- Zi Zo Isochronous input and output
- Ii Io Interrupt input and output
- Bi Bo Bulk input and output
wireshark解析usbmon数据
1 | 编译libpcap |
实例说明:硬盘识别过程
状态码:-115(-EINPROGRESS)—— 操作仍在进行;经常出现在BULK out/in中1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166ffff0008c53b1300 304760007 S Ci:2:001:0 s a3 00 0000 0001 0004 4 <
ffff0008c53b1300 304760010 C Ci:2:001:0 0 4 = 03020100
ffff0008c53b1300 304760013 S Co:2:001:0 s 23 01 0010 0001 0000 0
ffff0008c53b1300 304760016 C Co:2:001:0 0 0
ffff0008c38a9500 304880006 S Ii:2:001:1 -115:2048 4 <
ffff0008c53b1300 304880013 S Ci:2:001:0 s a3 00 0000 0001 0004 4 <
ffff0008c53b1300 304880075 C Ci:2:001:0 0 4 = 03020000
ffff0008c53b1300 304880134 S Ci:2:001:0 s a3 00 0000 0001 0004 4 <
ffff0008c53b1300 304880141 C Ci:2:001:0 0 4 = 03020000
ffff0008c53b1300 304880143 S Co:2:001:0 s 23 03 0004 0001 0000 0
ffff0008c53b1300 304880146 C Co:2:001:0 0 0
ffff0008c53b1300 304960006 S Ci:2:001:0 s a3 00 0002 0001 0008 8 <
ffff0008c53b1300 304960010 C Ci:2:001:0 0 8 = 03021000 55000000
ffff0008c53b1300 304960013 S Co:2:001:0 s 23 01 0014 0001 0000 0
ffff0008c53b1300 304960092 C Co:2:001:0 0 0
ffff0008c53b1300 304960092 S Co:2:001:0 s 23 01 001d 0001 0000 0
ffff0008c53b1300 304960095 C Co:2:001:0 0 0
ffff0008c53b1300 304960097 S Co:2:001:0 s 23 01 0019 0001 0000 0
ffff0008c53b1300 304960100 C Co:2:001:0 0 0
ffff0008c53b1300 304960101 S Co:2:001:0 s 23 01 0010 0001 0000 0
ffff0008c53b1300 304960104 C Co:2:001:0 0 0
ffff0008c53b1300 304960105 S Ci:2:001:0 s a3 00 0000 0001 0004 4 <
ffff0008c53b1300 304960107 C Ci:2:001:0 0 4 = 03020000
// 设备描述符请求,主机请求设备描述符(0x0100)
// 设备响应:USB 2.0设备,厂商ID 0x1201,产品ID 0x2003
ffff0008c53b1300 305060007 S Ci:2:003:0 s 80 06 0100 0000 0008 8 <
ffff0008c53b1300 305060669 C Ci:2:003:0 0 8 = 12012003 00000009
ffff0008c53b1300 305060673 S Co:2:003:0 s 00 31 0028 0000 0000 0
ffff0008c53b1300 305060686 C Co:2:003:0 0 0
// 配置描述符请求
ffff0008c53b1300 305060688 S Ci:2:003:0 s 80 06 0100 0000 0012 18 <
ffff0008c53b1300 305060718 C Ci:2:003:0 0 18 = 12012003 00000009 c20b3c20 10010102 0301
ffff0008c53b1300 305060721 S Ci:2:003:0 s 80 06 0f00 0000 0005 5 <
ffff0008c53b1300 305060745 C Ci:2:003:0 0 5 = 050f2a00 03
ffff0008c53b1300 305060747 S Ci:2:003:0 s 80 06 0f00 0000 002a 42 <
ffff0008c53b1300 305060772 C Ci:2:003:0 0 42 = 050f2a00 03071002 06000000 0a100300 0e00020a ff071410 0a000100 00000011
ffff0008c53b1300 305060778 S Ci:2:003:0 s 80 06 0200 0000 0009 9 <
ffff0008c53b1300 305060799 C Ci:2:003:0 0 9 = 09027900 01010080 70
ffff0008c53b1300 305060800 S Ci:2:003:0 s 80 06 0200 0000 0079 121 <
ffff0008c53b1300 305060825 C Ci:2:003:0 0 121 = 09027900 01010080 70090400 00020806 50000705 81020004 00063007 00000007
// 字符串描述符请求
// 返回支持英语(0x0409)
ffff0008c53b0500 305060836 S Ci:2:003:0 s 80 06 0300 0000 00ff 255 <
ffff0008c53b0500 305060856 C Ci:2:003:0 0 4 = 04030904
// 产品字符串请求
// 解码为"One Touch SSD"(西数One Touch固态硬盘)
ffff0008c53b0500 305060858 S Ci:2:003:0 s 80 06 0302 0409 00ff 255 <
ffff0008c53b0500 305060882 C Ci:2:003:0 0 28 = 1c034f00 6e006500 20005400 6f007500 63006800 20005300 53004400
// 厂商字符串请求
// 解码为"Seagate"(西数硬盘)
ffff0008c53b0500 305060884 S Ci:2:003:0 s 80 06 0301 0409 00ff 255 <
ffff0008c53b0500 305060909 C Ci:2:003:0 0 16 = 10035300 65006100 67006100 74006500
// 序列号请求:
// 解码为"000000000000NAD13NE"
ffff0008c53b0500 305060911 S Ci:2:003:0 s 80 06 0303 0409 00ff 255 <
ffff0008c53b0500 305060938 C Ci:2:003:0 0 34 = 22033000 30003000 30003000 30003000 30004e00 41004400 31003300 4e004500
ffff0008c53b0500 305141003 S Co:2:003:0 s 00 09 0001 0000 0000 0
ffff0008c53b0500 305141023 C Co:2:003:0 0 0
ffff0008c53b1900 305141152 S Co:2:003:0 s 01 0b 0001 0000 0000 0
ffff0008c53b1900 305141166 C Co:2:003:0 0 0
ffff0008cae05800 305160089 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305160106 S Bi:2:003:1 -115 36 <
// 大容量存储设备初始化
// SCSI命令交换
// 主机发送INQUIRY命令,设备响应确认是SCSI设备
ffff0008cae04400 305160113 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12000000 24000000 00000000 00000000
ffff0008cae04400 305160138 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305160339 C Bi:2:003:1 0 36 = 00000602 5b000002 53656167 61746520 4f6e6520 546f7563 68205353 44000000
ffff0008cae05800 305160343 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305160379 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305160383 S Bi:2:003:1 -115 96 <
ffff0008cae04400 305160387 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12000000 60000000 00000000 00000000
ffff0008cae04400 305160401 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305160766 C Bi:2:003:1 0 96 = 00000602 5b000002 53656167 61746520 4f6e6520 546f7563 68205353 44000000
ffff0008cae05800 305160770 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305190196 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305190201 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305190204 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12010000 04000000 00000000 00000000
ffff0008cae04400 305190219 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305190588 C Bi:2:003:1 0 4 = 00000008
ffff0008cae05800 305190591 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305190597 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305190600 S Bi:2:003:1 -115 12 <
ffff0008cae04400 305190603 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12010000 0c000000 00000000 00000000
ffff0008cae04400 305190617 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305190979 C Bi:2:003:1 0 12 = 00000008 008083b0 b1b2c1c2
ffff0008cae05800 305190982 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305190986 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305190990 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305190993 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12010000 04000000 00000000 00000000
ffff0008cae04400 305191008 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305191369 C Bi:2:003:1 0 4 = 00000008
ffff0008cae05800 305191372 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305191376 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305191379 S Bi:2:003:1 -115 12 <
ffff0008cae04400 305191382 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12010000 0c000000 00000000 00000000
ffff0008cae04400 305191396 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305191760 C Bi:2:003:1 0 12 = 00000008 008083b0 b1b2c1c2
ffff0008cae05800 305191763 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305191767 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305191770 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305191773 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12018000 04000000 00000000 00000000
ffff0008cae04400 305191787 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305192151 C Bi:2:003:1 0 4 = 00800010
ffff0008cae05800 305192154 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305192157 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305192160 S Bi:2:003:1 -115 20 <
// 读取容量命令:
// 主机请求磁盘容量信息
ffff0008cae04400 305192163 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12018000 14000000 00000000 00000000
ffff0008cae04400 305192177 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305192541 C Bi:2:003:1 0 20 = 00800010 30303030 30303030 4e414431 334e4551
ffff0008cae05800 305192544 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305192551 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305192554 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305192557 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12018300 04000000 00000000 00000000
ffff0008cae04400 305192571 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305192936 C Bi:2:003:1 0 4 = 0083000c
ffff0008cae05800 305192939 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305192943 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305192946 S Bi:2:003:1 -115 16 <
ffff0008cae04400 305192950 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 12018300 10000000 00000000 00000000
ffff0008cae04400 305192968 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305193326 C Bi:2:003:1 0 16 = 0083000c 01030008 500014a0 00000001
ffff0008cae05800 305193330 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305193333 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305193336 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305193340 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 1201b000 04000000 00000000 00000000
ffff0008cae04400 305193353 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305193717 C Bi:2:003:1 0 4 = 00b0003c
ffff0008cae05800 305193720 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305193723 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305193727 S Bi:2:003:1 -115 64 <
ffff0008cae04400 305193730 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 1201b000 40000000 00000000 00000000
ffff0008cae04400 305193744 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305194110 C Bi:2:003:1 0 64 = 00b0003c 00000008 0000ffff 0000ffff 0000ffff ffffffff 000000ff 00000000
ffff0008cae05800 305194113 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305194117 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305194120 S Bi:2:003:1 -115 4 <
ffff0008cae04400 305194123 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 1201b100 04000000 00000000 00000000
ffff0008cae04400 305194136 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305194501 C Bi:2:003:1 0 4 = 00b1003c
ffff0008cae05800 305194504 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008cae05800 305194509 S Bi:2:003:3 -115 112 <
ffff0008cae04d00 305194513 S Bi:2:003:1 -115 64 <
ffff0008cae04400 305194516 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 1201b100 40000000 00000000 00000000
ffff0008cae04400 305194530 C Bo:2:003:4 0 32 >
ffff0008cae04d00 305194890 C Bi:2:003:1 0 64 = 00b1003c 00010003 00000000 00000000 00000000 00000000 00000000 00000000
ffff0008cae05800 305194893 C Bi:2:003:3 0 16 = 03000001 00000000 00000000 00000000
ffff0008ca19a900 305224435 S Bi:2:003:3 -115 112 <
ffff0008ca19bf00 305224445 S Bi:2:003:1 -115 4 <
ffff0008ca19a700 305235102 S Bi:2:003:3 -115 112 <
ffff0008ca19aa00 305235490 C Bi:2:003:1 0 4 = 17000000
ffff0008ca19b600 305291732 S Bi:2:003:3 -115 112 <
// 数据交换,开始大量数据交换,可能是读取分区表或文件系统信息?
ffff0008ca19aa00 305291737 S Bo:2:003:4 -115 32 = 01000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ffff0008ca19aa00 305291752 C Bo:2:003:4 0 32 >
ffff0008cb0c2e00 305300390 S Bi:2:003:3 -115 112 <
ffff0008c9bf9500 305308043 C Bi:2:003:1 0 4096 = 20800000 20800100 20800200 20800300 20800400 20800c00 20800d00 20801800
ffff00081ac17800 305308471 C Bi:2:003:1 0 4096 = 40800000 40800100 40800200 40800300 40800400 40800c00 40800d00 40801800
ffff00081ac16900 305318660 S Bi:2:003:3 -115 112 <
ffff00081ac17600 305318671 S Bi:2:003:1 -115 4096 <
实例说明:adb shell
Bo:2:003:2表示:Bulk输出,总线2,设备3,端点21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24ffff000820a6b228 1283730040 S Bo:2:003:2 -115 24 = 4f50454e 1d000000 00000000 22000000 00000000 b0afbab1
ffff000820a6be28 1283730048 S Bo:2:003:2 -115 34 = 7368656c 6c2c7632 2c544552 4d3d7874 65726d2d 32353663 6f6c6f72 2c707479
ffff000820a6b228 1283730203 C Bo:2:003:2 0 24 >
ffff000820a6be28 1283730217 C Bo:2:003:2 0 34 >
ffff0008c07e22f8 1283731484 C Bi:2:003:1 0 24 = 4f4b4159 05000000 1d000000 00000000 00000000 b0b4bea6
ffff0008c07e23f0 1283749814 C Bi:2:003:1 0 24 = 57525445 05000000 1d000000 18000000 00000000 a8adabba
ffff0008c07e24e8 1283749820 C Bi:2:003:1 0 24 = 01130000 00726f6f 74406331 3230302d 61646173 3a2f2320
ffff0008c07e22f8 1283770012 S Bi:2:003:1 -115 1048576 <
ffff000820a6be28 1283770043 S Bo:2:003:2 -115 24 = 57525445 1d000000 05000000 10000000 00000000 a8adabba
ffff000820a6b228 1283770046 S Bo:2:003:2 -115 16 = 050b0000 00333078 3132302c 30783000
ffff0008c07e23f0 1283770046 S Bi:2:003:1 -115 1048576 <
ffff0008c07e24e8 1283770047 S Bi:2:003:1 -115 1048576 <
ffff000820a6a028 1283770051 S Bo:2:003:2 -115 24 = 4f4b4159 1d000000 05000000 00000000 00000000 b0b4bea6
ffff000820a6be28 1283770092 C Bo:2:003:2 0 24 >
ffff000820a6b228 1283770097 C Bo:2:003:2 0 16 >
ffff000820a6a028 1283770099 C Bo:2:003:2 0 24 >
ffff0008c07e25e0 1283770226 C Bi:2:003:1 0 24 = 4f4b4159 05000000 1d000000 00000000 00000000 b0b4bea6
ffff0008c07e2010 1283770355 C Bi:2:003:1 0 24 = 57525445 05000000 1d000000 1d000000 00000000 a8adabba
ffff0008c07e2108 1283770358 C Bi:2:003:1 0 29 = 01180000 000d1b5b 4b0d726f 6f744063 31323030 2d616461 733a2f23 20
ffff0008c07e25e0 1283810009 S Bi:2:003:1 -115 1048576 <
ffff0008c07e2010 1283810011 S Bi:2:003:1 -115 1048576 <
ffff0008c07e2108 1283810011 S Bi:2:003:1 -115 1048576 <
ffff000820a6a028 1283810032 S Bo:2:003:2 -115 24 = 4f4b4159 1d000000 05000000 00000000 00000000 b0b4bea6
ffff000820a6a028 1283810045 C Bo:2:003:2 0 24 >
实例说明:硬盘拷贝4k文件
1 | root@tst:~# mount /dev/sdb1 /mnt/usbcat /sys/kernel/debug/usb/usbmon/0^C |
常用分析组合
开发阶段使用 动态调试 配合 debugfs;
遇到死锁或流程问题时使用 Ftrace;
发生崩溃时则依赖 Kdump + Crash 进行分析。











































































