linux 内存 - KO内存占用

news/2024/7/3 20:17:16

说明

  • KO(kernel module)占用的内存分为两部分:
  1. 静态占用 :ko insmod时系统固定分配的内存。
  2. 动态申请 :代码中动态申请的内存,由于申请方式不同,统计的方式也可能不同,例如:使用vmalloc和kmalloc申请内存,统计方式就不同;代码是否执行以及执行次数不同,统计结果也不同。

静态占用

  • KO静态占用内存是通过vmalloc分配的, 主要分为两部分
  1. core_layout
  2. init_layout
  • 可通过linux内核代码确认。
// 文件:linux_5.10/kernel/module.c
static struct module *layout_and_allocate(struct load_info *info, int flags)
{
    ...
    ndx = find_sec(info, ".data..ro_after_init");
    if (ndx)
            info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
    ...
    ndx = find_sec(info, "__jump_table");
    if (ndx)
            info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;

    /* Determine total sizes, and put offsets in sh_entsize.  For now
       this is done generically; there doesn't appear to be any
       special cases for the architectures. */
    layout_sections(info->mod, info);
    layout_symtab(info->mod, info);

    /* Allocate and move to the final place */
    err = move_module(info->mod, info);
    if (err)
            return ERR_PTR(err);

    /* Module has been copied to its final place now: return it. */
    mod = (void *)info->sechdrs[info->index.mod].sh_addr;
    kmemleak_load_module(mod, info);
    return mod;
}

static int move_module(struct module *mod, struct load_info *info)
{
...
    /* Do the allocs. */
    ptr = module_alloc(mod->core_layout.size);
...
    if (mod->init_layout.size) {
        ptr = module_alloc(mod->init_layout.size);
        ...
    }
...
}

void * __weak module_alloc(unsigned long size)
{       
    // 使用vmalloc申请内存
    return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
                        GFP_KERNEL, PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS,
                        NUMA_NO_NODE, __builtin_return_address(0));
}

占用统计

  1. lsmod 或 /proc/modules
  • lsmod打印的KO列表中有个size属性,表示KO内存占用。
  • lsmod 的数据来自/proc/modules。
~# lsmod 
Module                  Size  Used by    Tainted: GF 
xxxx_ive            234750  0 
xxx_ipcm               84490  0 
xxxx_tpu             26507  0 
xxxx_clock_cooling     4685  0 
xxxx_sys             21052  1 xxxx_ive
~# cat /proc/modules 
xxxx_ive 234750 0 - Live 0xffffffdf808a5000 (FO)
xxx_ipcm 84490 0 - Live 0xffffffdf80881000 (FO)
xxxx_tpu 26507 0 - Live 0xffffffdf80873000 (FO)
xxxxx_clock_cooling 4685 0 - Live 0xffffffdf8086e000 (FO)
xxxxx_sys 21052 1 xxxx_ive, Live 0xffffffdf80863000 (FO)
  • /proc/modules显示的size包括KO的init_size和core_size,少于实际静态占用,可通过以下节点查看分别大小。
~# cat /sys/module/xxxx_sys/initsize
~# cat /sys/module/xxxx_sys/coresize
  1. cat /proc/meminfo 查看vmallocUsed 项,cat /proc/vmallocinfo 中查看单个KO的内存占用。
~# cat /proc/meminfo
....
VmallocTotal:   67108863 kB
VmallocUsed:        2564 kB
VmallocChunk:          0 kB
....
~# cat /proc/vmallocinfo
....
0x(____ptrval____)-0x(____ptrval____)   28672 load_module+0x6fa/0x1c5a pages=6 vmalloc
0x(____ptrval____)-0x(____ptrval____)   12288 load_module+0x6fa/0x1c5a pages=2 vmalloc
0x(____ptrval____)-0x(____ptrval____)   32768 load_module+0x6fa/0x1c5a pages=7 vmalloc
0x(____ptrval____)-0x(____ptrval____)   90112 load_module+0x6fa/0x1c5a pages=21 vmalloc
0x(____ptrval____)-0x(____ptrval____)  241664 load_module+0x6fa/0x1c5a pages=58 vmalloc
....
  • 有些平台上VmallocUsed 显示为0 KB。

区别

* xxxx_ive
lsmod size:             234750
vmallocinfo size:       241664
  • 看/proc/vmallocinfo 中的数据和lsmod 数据差别在两点:
  1. 内存页(4096)对齐
  2. 多一内存页(栅栏页)

整体占用统计方法

  1. insmod/rmmod ko后cat /proc/meminfo 看available变化(但是不是很准确)。

http://www.niftyadmin.cn/n/4924358.html

相关文章

Netty:查看ByteBuf的实现类

io.netty.buffer.ByteBuf是一个抽象类,我们看看它最终的实现类。实现类有多个,具体用的是哪个实现类,跟分配ByteBuf的方式有关。 作为举例,分别用Unpooled和ByteBufAllocator.DEFAUL来分配一个ByteBuf。 package com.thb;import …

jQuery知识

DOM知识 alert(我是弹窗); prompt(弹窗输入);Dom元素节点获取 方式一:通过 id 获取 一个 元素节点(为什么是一个呢?因为 id 是唯一的) var div1 document.getElementById("box1"); 方式二:通过 标签名 获…

什么是行级锁和表级锁

行级锁和表级锁是数据库中常见的两种锁机制,用于在多个事务并发访问数据库时控制数据的访问权限和并发操作。 行级锁(Row-Level Locking): 行级锁是指在数据库表中对每一行数据进行锁定,只有被锁定的行才不能被其他事…

Vue中的的通信方式有几种?隔代组件的通信你用那种方式解决?

props/$emit 适用父子组件通信 ref与parent/children适用父子组件通信 attrs/listeners,provide/inject 适用于隔代组件通信 vuex,EventBus(事件总线) 适用于父子、隔代、兄弟组件通信 slot插槽方式 attrs实例 父组件(这时候我们传了两个参数title和type&…

YOLOv5源码中的参数超详细解析(2)— 配置文件yolov5s.yaml

前言:Hello大家好,我是小哥谈。YOLOv5配置了5种不同大小的网络模型,分别是YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x,其中YOLOv5n是网络深度和宽度最小但检测速度最快的模型,其他4种模型都是在YOLOv5n的基础上不断…

Java并发 | 常见线程安全容器

文章目录 简介一、Hash表🚣1、ConcurrentHashMap1.1 内部实现原理1.2 并发操作方法1.3 ConcurrentHashMap与Hashtable的比较 二、集合🚣2、CopyOnWriteArrayList2.1 内部实现原理2.2 Copy-On-Write(COW)设计思想2.3 实操 三、Map🚣3、Concurr…

BpBinder与PPBinder调用过程——Android开发Binder IPC通信技术

在Android系统中,进程间通信(IPC)是一个非常重要的话题。Android系统通过Binder IPC机制实现进程间通信,而Binder IPC通信技术则是Android系统中最为重要的进程间通信技术之一。本文将介绍Binder IPC通信技术的原理,并…

龙蜥开发者说:是挑战也是契机!我见证了国产操作系统的雄起 | 第 22 期

「龙蜥开发者说」第 22 期来了!开发者与开源社区相辅相成,相互成就,这些个人在龙蜥社区的使用心得、实践总结和技术成长经历都是宝贵的,我们希望在这里让更多人看见技术的力量。本期故事,我们邀请了龙蜥社区开发者肖微…