【发布时间】:2016-01-14 19:20:13
【问题描述】:
我的发行版(Ubuntu 14.04.3 LTS)似乎没有导出这个引用,所以我无法在模块加载时解析地址。我正在寻找另一种无需重新编译内核即可确定地址的方法。
我在 macbook pro 上以访客身份在 VMware Fusion 下运行。内核是 3.13.0-74-generic。
提前致谢
【问题讨论】:
我的发行版(Ubuntu 14.04.3 LTS)似乎没有导出这个引用,所以我无法在模块加载时解析地址。我正在寻找另一种无需重新编译内核即可确定地址的方法。
我在 macbook pro 上以访客身份在 VMware Fusion 下运行。内核是 3.13.0-74-generic。
提前致谢
【问题讨论】:
使用kallsyms_lookup_name。它在linux/kallsyms.h 中定义为
unsigned long kallsyms_lookup_name(const char *name);
用法很简单:
struct page *my_mem_map = (struct page*)kallsyms_lookup_name("mem_map");
kallsyms_lookup_name 为自内核 2.6.33 以来的模块导出。
对于较早的内核,或一次查找多个符号,可以使用通用函数kallsyms_on_each_symbol。它遍历所有符号并为它们调用用户指定的函数。
【讨论】:
CONFIG_NEED_MULTIPLE_NODES 配置选项,则会导出符号 mem_map。但是使用kallsyms_lookup_name 搜索并不取决于符号是否被导出。
也许这个答案对你来说太晚了@owenh。我正在为正在寻找有关 mem_map 数组的相同问题的人回答它。因为到目前为止,我找不到任何关于为什么找不到 mem_map 的明确答案。在追查了pte_page 的工作原理后,我将在这里学到的一切记录下来。
如果找不到 mem_map 数组,可能是因为内核使用了虚拟连续的 mem_map 或者使用了sparse memory model,两者都没有
物理上连续的 mem_map 数组。相反,它可能以vmemmap 或mem_section 作为起点来查找所有page struct。这是由include/asm-generic/memory_model.h 中的这些宏 (CONFIG_FLATMEM/DISCONTIGMEM/CONFIG_SPARSEMEM_VMEMMAP/CONFIG_SPARSEMEM) 决定的。您可以使用类似的方法检查内核编译配置标志
sudo cat /boot/config-`uname -r` |grep CONFIG_SPARSEMEM_VMEMMAP
CONFIG_SPARSEMEM_VMEMMAP 模式下,page struct 数组从 vmemmap 开始,vmemmap 位于固定位置 0xffffea0000000000。
#define VMEMMAP_START _AC(0xffffea0000000000, UL)
#define vmemmap ((struct page *)VMEMMAP_START)
而在CONFIG_SPARSEMEM 模式下,page struct 数组通过名为 mem_section 的二维数组进行管理。
为了了解内核如何使用它,我们可以学习内核如何在给定页面的pte 的情况下获取页面的page struct。这个宏被称为pte_page(在arch/x86/include/asm/pgtable.h中)。它将 pte 转换为 pfn。使用该pfn,它可以使用vmemmap 或mem_section 定位page struct。这是include/asm-generic/memory_model.h。
【讨论】: