struct meminfo分析

本文详细介绍了Linux内核3.4.0在Android 4.1系统中如何使用struct meminfo收集和管理内存信息。从boot阶段的TAG传递,到meminfo信息收集、检查,再到最终的memblock结构用于内存区域的保存和分配。解析了内存信息的来源、检查过程,并指出parse_tag_mem32()在处理ATAG_MEM时的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Chipset:MSM8x25Q

Codebase:Android 4.1

Linux Kernel: 3.4.0

 

         在linux Kernel中,一开始内存相关的信息是由struct meminfo来保存的,每个物理连续的内存区域被保存为meminfo中的一个元素,也就是说在Linux使用中,整块物理内存可能是不连续的,可能其中某一中间区域是被其他cpu给使用掉了。

         那么内存相关信息又是从哪里收集到的呢,系统在boot阶段,如u-boot会将当前物理内存linux可以使用的部分通过TAG的形式传递给linux内核。Qualcomm使用的是叫lk的boot,不管用的是哪种boot类型,使用TAG来传递参数的原理是一样的。

         下面我们看下Linux内核是如何收集内存信息的。 

Meminfo信息收集

系统启动有如下流程:

start_kernel -> setup_arch -> setup_machine_tags-> parse_tags -> parse_tag.

static int __init parse_tag(const struct tag *tag)
{
	extern struct tagtable __tagtable_begin, __tagtable_end;
	struct tagtable *t;

	for (t = &__tagtable_begin; t < &__tagtable_end; t++)
		if (tag->hdr.tag == t->tag) {
			t->parse(tag);
			break;
		}

	return t < &__tagtable_end;
}

__tagtable_begin被定义在kernel/arch/arm/kernel/vmlinux.lds.S中:

.init.tagtable : {
		__tagtable_begin = .;
		*(.taglist.init)
		__tagtable_end = .;
	}

另外,在arch/arm/kernel/setup.c中有如下函数定义:

static int __init parse_tag_mem32(const struct tag *tag)
{
	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}
__tagtable(ATAG_MEM, parse_tag_mem32);

__tagtable是个宏定义:

#define __tagtable(tag, fn) \
static const struct tagtable__tagtable_##fn __tag = { tag, fn }
里面的__tag的宏定义又如下:

#define __tag __used__attribute__((__section__(".taglist.init")))

         __attribute__是一个特殊的GNU关键字,在这里的用法是:告诉编译器需要将其作用的函数或者数据放入”.taglist.init”这一段区域。

也就是说由__tagtable定义的函数将会被放在section“.taglist.init” 这个区域,而且__tagtable_begin指向的就是这个区域的首地址。所以在parse_tag()做for循环调用的时候,

必然会调用到parse_tag_mem32()。

  &nbs

### 关于 `dumpsys meminfo` 只显示核心应用内存信息的原因 当执行 `dumpsys meminfo` 命令时,默认情况下只会显示系统中一些关键进程和服务的信息,这主要是为了简化输出并提高效率。具体来说,在 Android 系统内部实现上,命令会优先关注那些被认为是“重要”的应用程序和组件。 对于获取应用层内存信息的过程涉及到多个层次的调用链路。例如,在 Java 层面通过 `getMemoryInfo()` 和 `getPss()` 函数来收集数据;而在本地代码层面,则有如下所示的关键逻辑: ```cpp // frameworks/base/core/jni/android_os_Debug.cpp struct graphics_memory_pss graphics_mem; if (read_memtrack_memory(pid, &graphics_mem) == 0) { ... } ``` 此段 C++ 代码展示了读取特定进程 ID (`pid`) 对应图形内存 PSS 数据的具体操作[^1]。然而,这种默认行为并不意味着无法查看全部的应用程序内存详情。 ### 解决方案:使 `dumpsys meminfo` 显示所有应用内存信息 要让 `dumpsys meminfo` 输出更详尽的内容,可以采用以下几种方式之一: #### 方法一:使用 `-a` 参数 最简单的方式是在运行该命令时加上参数 `-a` 或者 `--all` ,这样就可以强制工具列举出设备上的每一个正在运行的应用及其占用资源情况: ```bash adb shell dumpsys meminfo -a ``` 这种方法能够提供更为全面的数据集给开发者用于调试目的。 #### 方法二:指定包名查询单个 App 如果只关心某个特定 APP 的内存状况而不必看到整个系统的状态,那么可以直接指定目标 APK 的包名称作为参数传递进去: ```bash adb shell dumpsys meminfo com.example.appname ``` 这种方式不仅限定了范围从而减少了不必要的干扰项,同时也提高了检索速度与准确性。 #### 方法三:修改源码重新编译(不推荐) 理论上还可以通过对 AOSP 中的相关模块进行定制化开发以改变其工作模式,但这通常不是普通用户所能轻易做到的事情,并且可能会带来兼容性和稳定性方面的问题。因此除非确实有必要并且具备相应技术实力的情况下才考虑这么做。 ### 相关问题 1. 如何理解 `dumpsys meminfo` 报告中的各项指标含义? 2. 使用 `dumpsys meminfo` 进行性能优化时应该注意哪些事项? 3. 在不同版本的 Android 上,`dumpsys meminfo` 是否存在差异?如果有,主要体现在哪里? 4. 当发现某款应用消耗过多内存时,有哪些常见的排查手段可以帮助定位问题所在? : 来自参考资料描述了如何在底层访问特定进程的图形内存信息。 [^2]: 描述了从 MemBinder 到 AMS 再到 Debug 类的一系列调用来完成内存信息采集过程的一部分。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值