• 调试 dpdk 应用程序的coredump整理


    稳定复现的 coredump
    打开 dpdk 相关的 debug开关,重新编译
    mbuf debug
    malloc debug 
    mempool debug
    给 dpdk 源码加检查或日志,重新编译
    无法稳定复现的 coredump
    打开大页内存的 coredump
    案例
    字节序导致取地址不对,从而踩内存
    多线程竞争资源导致

    稳定复现的 coredump

    打开 dpdk 相关的 debug开关,重新编译

    # grep -i "DEBUG" common_base  | grep -Ei "malloc|mbuf|mempool"
    CONFIG_RTE_MALLOC_DEBUG=n
    CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n
    CONFIG_RTE_LIBRTE_OCTEONTX_MEMPOOL_DEBUG=n
    CONFIG_RTE_LIBRTE_MBUF_DEBUG=n

    mbuf debug

    malloc debug 

    mempool debug

    当开启RTE_LIBRTE_MEMPOOL_DEBUG时,申请mempool中的一个元素时,比如mbuf, 在mbuf的申请和释放出都会调用rte_mempool_check_cookies这个函数,对mbuf的cookie值进行校验。

    其校验原理可以理解为:

    1)在申请mbuf时,校验是否为cookie2,是,则对其打上cookie1的标记,不是,则panic;

    2)对释放mbuf是对其校验是否为cookie1,是,则打上cookie2,不是则 panic;

    简单的理解即mbuf的申请和释放处于两种状态,当任何一种动作(申请或释放)做了两次,都会产生panic;

    这个开关的存在,正好可以解决我们这个多线程重复free mbuf的问题。

    给 dpdk 源码加检查或日志,重新编译

    比如 对于 dpdk 从 mempool 中申请 的  mbuf 的相关的 core;

    (1)有可能是一个 mbuf 被多个线程给释放了?

    针对这种情况,可以自己封装 dpdk 的 struct rte_mbuf,添加一个 core_id,core_id 是申请 mbuf 时的线程的 core_id;

    释放的时候,比较下释放的 core_Id 和 申请的 core_id 是否是同一个;

    (2)一个mbuf 被一个线程的多处给释放了?

    可以自己封装  dpdk 的 struct rte_mbuf 结构;仿造上面的例子,申请的时候记录状态1;

    释放的时候,检查处于状态1,则设置状态2,记录释放的函数(通过函数宏的方式进行释放,可以记录上层函数),进行释放;

    如果存在再次释放,则已经处于状态2,检查失败;

    无法稳定复现的 coredump

    打开大页内存的 coredump

    设置 /proc/PID/coredump_filter 的参数;

    程序崩溃 或 使用gcore工具 生成进程的core文件时,可以通过设定内核转储掩码来筛选需要dump的部分内存。

    可以设置为 000000ff 来打印大页内存相关;

    支持以下7种内存:
     
      - (bit 0) anonymous private memory(匿名私有内存段)
      - (bit 1) anonymous shared memory(匿名共享内存段)
      - (bit 2) file-backed private memory(file-backed 私有内存段):文件映射的内存
      - (bit 3) file-backed shared memory(file-bakced 共享内存段)
      - (bit 4) ELF header pages in file-backed private memory areas (it is
                effective only if the bit 2 is cleared)(ELF 文件映射,只有在bit 2 复位的时候才起作用)
      - (bit 5) hugetlb private memory(大页面私有内存) :mmap 映射的MAP_HUGETLB类型数据
      - (bit 6) hugetlb shared memory(大页面共享内存)
      - (bit 7) DAX private memory
      - (bit 8) DAX shared memory
     
    可以通过修改文件/proc/<pid>/coredump_filter来筛选需要dump的内存段。
    /proc/<pid>/coredump_filter中的值为16进制,默认值是0x33,二进制为 0011 0011;
    也即发生coredump时会将所有anonymous内存、ELF头页面、hugetlb private memory内容保存。

    mempool中存储的每一个对象的结构分3部分,首部,数据和尾部。每一部分都填充以做到字节对齐,在调试模式首部和尾部还可以加上cookie。

    ../../../_images/mempool_obj.png

    #define RTE_MEMPOOL_HEADER_COOKIE2  0xf2eef2eedadd2e55ULL /**< Header cookie. */

    COOKIe

    static void
    mempool_add_elem(struct rte_mempool *mp, void *obj, phys_addr_t physaddr)
    {
        struct rte_mempool_objhdr *hdr;
        struct rte_mempool_objtlr *tlr __rte_unused;
    
        /* set mempool ptr in header */
        hdr = RTE_PTR_SUB(obj, sizeof(*hdr));
        hdr->mp = mp;
        hdr->physaddr = physaddr;
        STAILQ_INSERT_TAIL(&mp->elt_list, hdr, next);
        mp->populated_size++;
    
    #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
        hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2;
        tlr = __mempool_get_trailer(obj);
        tlr->cookie = RTE_MEMPOOL_TRAILER_COOKIE;
    #endif
    
        /* enqueue in ring */
        rte_mempool_ops_enqueue_bulk(mp, &obj, 1);
    }

    【DPDK17.11】记录一次由dpdk的野指针造成的coredump过程

  • 相关阅读:
    Heap(堆)和stack(栈)有的区别是什么。
    i++和++i的深入理解
    JDBC之java数据库的连接与简单的sql语句执行
    java前三本基础知识总结
    数据库的一些基础
    SQL 同时查看2个表
    JMeter 问题
    Linux 常用命令
    java io (一)
    验证密码必须是字母加数字的组合
  • 原文地址:https://www.cnblogs.com/dream397/p/14719015.html
Copyright © 2020-2023  润新知