2025年转台轴承厂家推荐榜单:立车转台轴承源头厂家精选 - 品牌推荐官
2025/12/23 15:25:39
Linux的Dynamic debug功能简单讲了下如何使用。再来回顾下其概念和用法。
Dynamic Debug 是 Linux 内核的动态调试功能,允许在运行时动态开启/关闭特定的pr_debug()和dev_dbg()输出,而无需重新编译内核。
核心特点:
主控制文件:/sys/kernel/debug/dynamic_debug/control
# 查看所有可用的 debug 点$cat/sys/kernel/debug/dynamic_debug/control drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c:123[amdgpu]amdgpu_init=_"AMDGPU driver loaded\012"drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:456[amdgpu]amdgpu_device_init=_"Device init started\012"...# 启用特定模块的所有 debug 输出$echo'module amdgpu +p'>/sys/kernel/debug/dynamic_debug/control# 启用特定文件的 debug 输出$echo'file amdgpu_ring.c +p'>/sys/kernel/debug/dynamic_debug/control# 启用特定函数的 debug 输出$echo'func amdgpu_ring_init +p'>/sys/kernel/debug/dynamic_debug/control# 禁用 debug 输出$echo'module amdgpu -p'>/sys/kernel/debug/dynamic_debug/control位置:lib/dynamic_debug.c
/* 每个 pr_debug() 对应一个 _ddebug 结构 */struct_ddebug{constchar*modname;/* 模块名 */constchar*function;/* 函数名 */constchar*filename;/* 文件名 */constchar*format;/* 格式字符串 */unsignedintlineno:18;/* 行号 */unsignedintflags:8;/* 标志 (是否启用) */}__attribute__((aligned(8)));/* 标志定义 */#define_DPRINTK_FLAGS_PRINT(1<<0)/* 启用打印 */#define_DPRINTK_FLAGS_INCL_MODNAME(1<<1)#define_DPRINTK_FLAGS_INCL_FUNCNAME(1<<2)#define_DPRINTK_FLAGS_INCL_LINENO(1<<3)/* 读操作:显示所有 debug 点 */staticintddebug_proc_show(structseq_file*m,void*p){structddebug_iter*iter=m->private;struct_ddebug*dp=p;charflagsbuf[10];/* 格式化输出每个 debug 点的信息 */seq_printf(m,"%s:%u [%s]%s =%s \"%s\"\n",trim_prefix(dp->filename),dp->lineno,iter->table->mod_name,dp->function,ddebug_describe_flags(dp->flags,flagsbuf,sizeof(flagsbuf)),dp->format);return0;}/* 写操作:处理控制命令 */staticssize_tddebug_proc_write(structfile*file,constchar__user*ubuf,size_tlen,loff_t*offp){char*tmpbuf;intret;/* 限制输入大小 */if(len==0||len>PAGE_SIZE)return-EINVAL;/* 从用户空间复制命令 */tmpbuf=memdup_user_nul(ubuf,len);if(IS_ERR(tmpbuf))returnPTR_ERR(tmpbuf);/* 解析并应用控制命令 */ret=ddebug_exec_queries(tmpbuf,NULL);kfree(tmpbuf);if(ret<0)returnret;returnlen;}/* file_operations 定义 */staticconststructfile_operationsddebug_proc_fops={.owner=THIS_MODULE,.open=ddebug_proc_open,.read=seq_read,.llseek=seq_lseek,.release=seq_release_private,.write=ddebug_proc_write,};staticint__initdynamic_debug_init_debugfs(void){structdentry*dir;/* 创建 dynamic_debug 目录 */dir=debugfs_create_dir("dynamic_debug",NULL);if(!dir)return-ENOMEM;/* 创建 control 文件 */debugfs_create_file("control",0644,dir,NULL,&ddebug_proc_fops);return0;}fs_initcall(dynamic_debug_init_debugfs);/* include/linux/dynamic_debug.h */#ifdefCONFIG_DYNAMIC_DEBUG#definepr_debug(fmt,...)\do{\staticstruct_ddebug__aligned(8)\__section("__dyndbg")descriptor={\.modname=KBUILD_MODNAME,\.function=__func__,\.filename=__FILE__,\.format=(fmt),\.lineno=__LINE__,\.flags=_DPRINTK_FLAGS_DEFAULT,\};\if(unlikely(descriptor.flags&_DPRINTK_FLAGS_PRINT))\__dynamic_pr_debug(&descriptor,pr_fmt(fmt),\##__VA_ARGS__);\}while(0)#else#definepr_debug(fmt,...)no_printk(fmt,##__VA_ARGS__)#endif工作原理:
pr_debug()编译时生成一个_ddebug结构_ddebug放在特殊段__dyndbg中_ddebug结构flags字段flags决定是否打印/* drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c */intamdgpu_ring_init(structamdgpu_device*adev,structamdgpu_ring*ring,unsignedintmax_dw,structamdgpu_irq_src*irq_src){/* 这些 pr_debug 默认不输出 */pr_debug("Initializing ring %s\n",ring->name);pr_debug("Ring size: %u DWs\n",max_dw);/* ... 初始化逻辑 ... */pr_debug("Ring %s initialized successfully\n",ring->name);return0;}# 启用该文件的所有 debug 输出$echo'file amdgpu_ring.c +p'>/sys/kernel/debug/dynamic_debug/control# 现在执行操作会看到 debug 信息$dmesg|tail[123.456]amdgpu: Initializing ring gfx[123.457]amdgpu: Ring size:1024DWs[123.458]amdgpu: Ring gfx initialized successfully# 禁用$echo'file amdgpu_ring.c -p'>/sys/kernel/debug/dynamic_debug/control# 按行号启用$echo'file amdgpu_ring.c line 123 +p'>control# 组合条件(文件 + 函数)$echo'file amdgpu_ring.c func amdgpu_ring_init +p'>control# 格式化标志$echo'module amdgpu +pflmt'>control# +p: 启用打印# +f: 包含函数名# +l: 包含行号# +m: 包含模块名# +t: 包含线程 ID# 使用通配符$echo'file amdgpu_* +p'>control $echo'func *_init +p'>control/* 关闭时的性能开销 */if(unlikely(descriptor.flags&_DPRINTK_FLAGS_PRINT))// 仅一次位测试__dynamic_pr_debug(&descriptor,...);// 不执行/* * unlikely() 提示:分支预测优化 * 位测试:极快的 CPU 操作 * 关闭时:几乎零开销(<1 纳秒) */| 方式 | 运行时控制 | 性能开销 | 灵活性 | 需要重启 |
|---|---|---|---|---|
| printk | ❌ | 高 | 低 | ✅ |
| Dynamic Debug | ✅ | 极低 | 高 | ❌ |
| Ftrace | ✅ | 中 | 极高 | ❌ |
| 条件编译 (#ifdef) | ❌ | 无 | 低 | ✅ |
Dynamic Debug 展示了 DebugFS 的典型应用模式:
复杂的写操作:
大量数据的读操作:
运行时控制内核行为: