内核由于共享内存地址空间,如果没有合适的工具,很多踩内存的问题即使复现,也无法快速定位;

在新的内核版本中引入了一个新工具hardware breakpoint,其能够监视对指定的地址的特定类型(读/写)的数据访问,有利于该类问题的定位;

以下是一个使用该工具的例子(来自内核代码linux-3.10/samples/hw_breakpoint/data_breakpoint.c)

struct perf_event * __percpu *sample_hbp;

static char ksym_name[KSYM_NAME_LEN] = "pid_max";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
" write operations on the kernel symbol"); static void sample_hbp_handler(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
printk(KERN_INFO "%s value is changed\n", ksym_name);
dump_stack();
printk(KERN_INFO "Dump stack from sample_hbp_handler\n");
} static int __init hw_break_module_init(void)
{
int ret;
struct perf_event_attr attr; hw_breakpoint_init(&attr);
attr.bp_addr = kallsyms_lookup_name(ksym_name);
attr.bp_len = HW_BREAKPOINT_LEN_4;
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL);
if (IS_ERR((void __force *)sample_hbp)) {
ret = PTR_ERR((void __force *)sample_hbp);
goto fail;
} printk(KERN_INFO "HW Breakpoint for %s write installed\n", ksym_name); return 0; fail:
printk(KERN_INFO "Breakpoint registration failed\n"); return ret;
} static void __exit hw_break_module_exit(void)
{
unregister_wide_hw_breakpoint(sample_hbp);
printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
} module_init(hw_break_module_init);
module_exit(hw_break_module_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("K.Prasad");
MODULE_DESCRIPTION("ksym breakpoint");

注意:

  • 1、各个不同的CPU有同时支持的hardwarebreakpoint数量限制,对X86,为4个.

    所以对于随机的内存踩踏(频繁的申请、使用、释放)是很难处理的,比较适合固定的地址踩踏

  • 2、指定的回调函数的调用时机:对X86,如果监视的是数据地址,则是在访问该数据的指令执行完成后,通过exception触发回调,如果监视的是指令地址,则是在该指令被执行前通过exception触发回调

    1. 该方式只能监视通过CPU访问地址的情况,对DMA就无能为力了

补充:

如何跟踪指令地址

  • 1、该工具用于跟踪指令地址(函数等)的访问,这个时候attr.bp_type需要设置为HW_BREAKPOINT_X

    关于PER_CPU变量的跟踪

1、获取per_cpu变量的地址

如果跟踪的是内核的per_cpu变量,那么用kallsyms_lookup_name获取到的地址不是per_cpu变量的实际地址,仅仅是该per_cpu变量相对于各个cpu自己的per_cpu数据存放区起始地址的偏移,需要通过per_cpu_ptr获取到真实的地址,比如:

	addr = kallsyms_lookup_name("gcwq_nr_running");
addr = (unsigned long)per_cpu_ptr((atomic_t *)addr,cpu);
attr.bp_addr = addr

2、关于可用的hw breakpoint数量

由于CPU硬件支持的hw breakpoint数量非常有限,当前CPU和核心数量较多,很多时候不可能为每个CPU核心对于的per cpu变量都注册hw breakpoint,但是很多per_cpu变量的改写,甚至是读取,都限定在本CPU,而不是所有的CPU,如果是出于内核执行跟踪的目的,就没有必要把要在其它CPU上访问的per_cpu变量地址都注册在当前CPU的hw breakpoint了,这时就可以修改hw breakpoint接口register_wide_hw_breakpoint,把其中的for_each_online_cpu循环修改为仅仅处理当前CPU即可

内核模块踩内存问题定位利器- hardware breakpoint的更多相关文章

  1. 记一次《C语言踩内存》问题定位有感

    踩内存问题,个人认为算是比较容易出现但是有很难定位的问题,被踩者轻者功能瘫痪,重者一命呜呼,直接诱发死机.产生踩内存的的原因也比较多样,比较典型的有如下几种: 数组越界访问 字符串越界操作 直接操作野 ...

  2. Android内存泄漏检测利器:LeakCanary

    Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...

  3. 根据内存布局定位的一个fastdfs坑

    在使用fastdfs时,编写数据上传代码时,遇到一个坑.最终根据指针对应的内存布局定位到一个其client API的一个坑,值得记录一下.具体是在 tracker_connect_server() 这 ...

  4. 一个未完成的2.6.32-220内核踩内存crash分析记录

    遇到一个crash,log如下: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff81 ...

  5. 构造函数,C++内存管理,内存泄漏定位

    构造函数 1.构造顺序 虚基类构造函数,基类构造函数,类对象构造函数,自己的构造函数 2.必须使用初始化列表 (1) 引用成员,常量成员: (2) 基类没默认构造函数(自己重载覆盖了), (3)类对象 ...

  6. C++ 踩内存

    1.从上往下,栈在堆上面(记忆方法:站在堆上面),二者向里压缩,也就是说,栈地址减少,堆地址增加.栈顶是小地址. 2.模拟踩内存,让程序崩溃.代码如下: int main(int argc, char ...

  7. 内存问题检查利器——Purify

    内存问题检查利器——Purify 一.           引言 我们都知道软件的测试(在以产品为主的软件公司中叫做QA—Quality Assessment)占了整个软件工程的30% -50%,但有 ...

  8. Java内存泄漏定位

    Java虚拟机内存分为五个区域:方法区,堆,虚拟机栈,本地方法栈,程序计数器.其中方法区和堆是java虚拟机共享的内存区域,虚拟机栈,本地方法栈,程序计数器是线程私有的. 程序计数器(Program ...

  9. Linux进程内存分析和内存泄漏定位

    在Linux产品开发过程中,通常需要注意系统内存使用量,和评估单一进程的内存使用情况,便于我们选取合适的机器配置,来部署我们的产品. Linux本身提供了一些工具方便我们达成这些需求,查看进程实时资源 ...

  10. Android 内存泄漏分析利器——leakcanary

    LeakCanary Android 和 Java 内存泄露检测. “A small leak will sink a great ship.” - Benjamin Franklin 千里之堤, 毁 ...

随机推荐

  1. 【教程】解决npm 报错 npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

    问题描述 只要在控制台执行npm,不论有没有参数,都会有此警告: npm WARN config global `--global`, `--local` are deprecated. Use `- ...

  2. C# 推荐一种开机自启动的方式

    概述(Overview) 网上多数搜索结果以注册表设置为优先,这个方法需要管理员权限,实际工作中可能并不适用.这个方法是直接写到用户开机自启动目录里,系统开机会带着一起启动.(Most search ...

  3. Jmeter函数助手31-changeCase

    changeCase函数用于字符转换大小写. 字符串修改:填入需要转换的字符 更改案例模式UPPER(默认),LOWER,CAPITALIZE:不填默认UPPER,UPPER全部转换为大写,LOWER ...

  4. Jmeter函数助手8-counter

    counter函数用于线程计数,类似计数器. TRUE每个用户有自己的计数器:FALSE使用全局计数器:即线程之间是否需要共享累加计数器,TRUE否,FALSE是 存储结果的变量名(可选) 1.线程之 ...

  5. 银河麒麟V10高级服务器编译安装pg13.4

    安装postgres依赖 yum install -y openssl openssl-devel pam pam-devel libxml2 libxml2-devel libxslt libxsl ...

  6. 【Vue】el-select 数据过多替代方案

    一.需求问题: 一开始就考虑使用简单el-select选取数据,但是后面数据量增多, 超过一千条开始,组件会很卡不好用,第二个是接口也慢了 数据量多的话是有一个filterable做支持了,可以输入关 ...

  7. 【DataBase】局域网访问Windows系统下的MySQL8

    Windows服务主机已经安装好MySQL8并且配置了用户密码 MySQL8更改用户密码: ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' ...

  8. 【转载】 NVIDIA RTX2080ti不支持P2P Access,这是真的么?

    原文地址: http://www.gpus.cn/gpus_list_page_techno_support_content?id=30 ------------------------------- ...

  9. 《Python数据可视化之matplotlib实践》 源码 第四篇 扩展 第十三章

    图  13.10 import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np mpl.rcParams[&q ...

  10. NVIDIA公司推出的GPU运行环境下的机器人仿真环境(NVIDIA Isaac Gym)—— 到底实现了什么功能,意义价值又是什么???

    相关内容: NVIDIA公司推出的GPU运行环境下的机器人仿真环境(NVIDIA Isaac Gym)的安装--强化学习的仿真训练环境 ================================ ...