【内存踩踏分析】

内存踩踏分析:

搞底层开发的人一定听过内存踩踏这个令人可怕的专业词语,轻则功能错乱,重则死机崩溃。关键是排查起来还费劲,尤其是在内核驱动中。因为当我们发现异常的时候,往往已经不是第一案发现场了,可能是第二、第三、第N现场了,作案人员可能早已逃离作案现场,在案发现场,可能不曾留下任何蛛丝马迹。有时可能有些蛛丝马迹,但也极为隐秘,很难找出来。当然你可以打开内核KASAN重新编译,再重新复现问题看能不能抓到一些有用的信息。但这样重新编译后,工作环境发生了变化,问题不一定能够复现。我最近遇到一个奇怪的问题,看上去很像内存踩踏。我一个结构体中的成员变量,在初始化之后,就再也没动过它了,可后面某次访问时,它的值突然就变成一个异常值了。种种迹象看起来很像是内存踩踏,于是我在这个变量前后加一些变量想看看踩踏的数据有没有啥规律,但是改了代码之后就复现不到了。由于我的变量是只读的,我就找找看有没有办法监控下这个变量的地址,当CPU往这个地址写数据的时候,自动把调用堆栈打印出来,那么就知道哪里在搞鬼了。我找到了以下方法验证可行,读和写都可以监控到,分享给C厂的小伙伴,希望大家以后遇到类似问题时,手上又多了一件破案的工具。对于那些非只读的场合,自己修改变量的值时,要先去掉监控,修改完了之后再打开监控。

解决方案:

#include <linux/kallsyms.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>

static struct perf_event * __percpu *sample_hbp;

static void sample_hbp_handler(struct perf_event *bp,
                               struct perf_sample_data *data,
                               struct pt_regs *regs) {
        printk(KERN_INFO "sample_hbp_handler!\n");
        dump_stack();
        printk(KERN_INFO "Dump stack from sample_hbp_handler!\n");
        BUG_ON(1); // 让系统停下来
}

static int my_hw_break_register(void *addr) {
        int ret;
        struct perf_event_attr attr;

        hw_breakpoint_init(&attr);
        attr.bp_addr = (__u64)addr; //64位系统
        attr.bp_len = HW_BREAKPOINT_LEN_8; //64位系统地址8字节,32位系统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 write %p installed.\n", addr);

        return 0;

fail:
        printk(KERN_INFO "HW Breakpoint registration failed for %p!\n", addr);

        return ret;
}

static void my_hw_break_unregister(void) {
        unregister_wide_hw_breakpoint(sample_hbp);
        printk(KERN_INFO "HW Breakpoint for write uninstalled.\n");
}

//测试代码
void test(void) {
    int a = 0;

    my_hw_break_register(&a);
    a = 1; //这样就会触发监控
    my_hw_break_unregister(); //用完了释放
}
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Linux 内核中,内存踩踏(memory thrashing)通常指的是频繁的页面置换操作,导致系统性能下降。要使用代码进行内存踩踏的检测,你可以考虑以下方法: 1. 监控页面交换(Page Swapping):内核提供了一些接口可以监控页面交换的情况。你可以使用 `vmstat` 命令来查看系统的交换情况。另外,你还可以通过读取 `/proc/vmstat` 文件来获取更详细的信息。 2. 分析页面缺失(Page Faults):页面缺失指的是进程试图访问的页面不在物理内存中,需要从磁盘读取。你可以使用 `sar` 命令来监视页面缺失的数量和频率。另外,可以通过读取 `/proc/pid/status` 文件,其中 `pid` 是进程的 ID,来获取特定进程的页面缺失信息。 3. 使用性能分析工具:使用性能分析工具可以更深入地分析内存踩踏问题。例如,你可以使用 `perf` 工具来收集系统性能数据,并使用 `perf report` 命令生成报告。另外,`sar` 命令也可以与 `perf` 结合使用,以收集更全面的性能数据。 4. 自定义监控代码:如果你需要更精细的内存踩踏检测,你可以在代码中添加监控机制。例如,你可以在关键代码段的前后记录页面交换或页面缺失的次数,并计算其频率。这样可以帮助你确定哪些代码段可能导致内存踩踏。 需要注意的是,内存踩踏是一个复杂的问题,可能由多个因素引起。因此,单独使用上述方法可能无法完全检测到内存踩踏的存在。综合使用多种监控手段和工具可以帮助你更好地分析和解决内存踩踏问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鲲君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值