Page_owner使用分析
Page_owner使用分析
目录
背景
在项目中有一部分camera相关的包括camera driver使用大于等于order3的内存分配点,并没有统计到camera provider进程上。所以想通过page_owner,调查一下相机没有统计到的内存申请。
原理
内存页被分配出去前,会走进 post_alloc_hook 函数,进行一些处理,post_alloc_hook函数会调用 set_page_owner 函数,完成内存页分配调用栈的保存。
inline void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags)
{
bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) &&
!should_skip_init(gfp_flags);
bool zero_tags = init && (gfp_flags & __GFP_ZEROTAGS);
bool reset_tags = true;
int i;
set_page_private(page, 0);
set_page_refcounted(page);
arch_alloc_page(page, order);
debug_pagealloc_map_pages(page, 1 << order);
/*
* Page unpoisoning must happen before memory initialization.
* Otherwise, the poison pattern will be overwritten for __GFP_ZERO
* allocations and the page unpoisoning code will complain.
*/kernel_unpoison_pages(page, 1 << order);
/*
* As memory initialization might be integrated into KASAN,
* KASAN unpoisoning and memory initializion code must be
* kept together to avoid discrepancies in behavior.
*//*
* If memory tags should be zeroed
* (which happens only when memory should be initialized as well).
*/if (zero_tags) {
/* Initialize both memory and memory tags. */for (i = 0; i != 1 << order; ++i)
tag_clear_highpage(page + i);
/* Take note that memory was initialized by the loop above. */init = false;
}
if (!should_skip_kasan_unpoison(gfp_flags)) {
/* Try unpoisoning (or setting tags) and initializing memory. */if (kasan_unpoison_pages(page, order, init)) {
/* Take note that memory was initialized by KASAN. */if (kasan_has_integrated_init())
init = false;
/* Take note that memory tags were set by KASAN. */reset_tags = false;
} else {
/*
* KASAN decided to exclude this allocation from being
* (un)poisoned due to sampling. Make KASAN skip
* poisoning when the allocation is freed.
*/SetPageSkipKASanPoison(page);
}
}
/*
* If memory tags have not been set by KASAN, reset the page tags to
* ensure page_address() dereferencing does not fault.
*/if (reset_tags) {
for (i = 0; i != 1 << order; ++i)
page_kasan_tag_reset(page + i);
}
/* If memory is still not initialized, initialize it now. */if (init)
kernel_init_pages(page, 1 << order);
/* Propagate __GFP_SKIP_KASAN_POISON to page flags. */if (kasan_hw_tags_enabled() && (gfp_flags & __GFP_SKIP_KASAN_POISON))
SetPageSkipKASanPoison(page);
set_page_owner(page, order, gfp_flags);
page_table_check_alloc(page, order);
}
static inline void set_page_owner(struct page *page,
unsigned int order, gfp_t gfp_mask)
{
if (static_branch_unlikely(&page_owner_inited))
__set_page_owner(page, order, gfp_mask);
}
noinline void __set_page_owner(struct page *page, unsigned int order,
gfp_t gfp_mask)
{
struct page_ext *page_ext = lookup_page_ext(page);//获取该page对应的struct page_ext结构体
depot_stack_handle_t handle;
if (unlikely(!page_ext))
return;
handle = save_stack(gfp_mask);//将该页被分配时的调用栈保存下来
__set_page_owner_handle(page_ext, handle, order, gfp_mask);
}
page_owner设计思路
扩展page结构体,增加成员变量用于存储该page被分配的调用栈及标志位,然后hook内存页的分配和释放接口,在内存页被分配时,保存调用栈信息,设置标志位;在内存页被释放的时候,清除调用栈信息,清除标志位。然后,通过一个debugfs的接口,将所有读取该接口时刻已经被分配出去的内存页的调用栈信息传递给用户态,并在用户态制作了一个工具,用于统计这些调用栈的信息。
Page_owner介绍
page owner is for the tracking about who allocated each page. It can be used to debug memory leak or to find a memory hogger.
官方介绍如下:
Page_owner支持
CONFIG_PAGE_OWNER=y
cmdline开启Page_owner
在BoardConfig.mk文件中,加上对应makefile的修改。
解析工具
page_owner.sh
#!/bin/bash
adb shell 'cat /sys/kernel/debug/page_owner > /data/local/tmp/page_owner_full.txt'
adb pull /data/local/tmp/page_owner_full.txt
grep -v ^PFN page_owner_full.txt > page_owner.txt
./page_owner_sort page_owner.txt sorted_page_owner.txt
复现问题
复现问题后执行:./page_owner.sh
最终生成有三个文件:
page_owner_full.txt
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135260 ns, free_ts 0 ns
PFN 530145 type Unmovable Block 517 type Unmovable Flags 0x4000000000000200(slab|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135468 ns, free_ts 0 ns
PFN 530146 type Unmovable Block 517 type Unmovable Flags 0x4000000000010200(slab|head|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135624 ns, free_ts 0 ns
PFN 530147 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135781 ns, free_ts 0 ns
PFN 530148 type Unmovable Block 517 type Unmovable Flags 0x4000000000010200(slab|head|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135833 ns, free_ts 0 ns
PFN 530149 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135885 ns, free_ts 0 ns
PFN 530150 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135937 ns, free_ts 0 ns
PFN 530151 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136406 ns, free_ts 0 ns
PFN 530152 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136614 ns, free_ts 0 ns
PFN 530153 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136770 ns, free_ts 0 ns
PFN 530154 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136822 ns, free_ts 0 ns
PFN 530155 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136979 ns, free_ts 0 ns
PFN 530156 type Unmovable Block 517 type Unmovable Flags 0x4000000000010200(slab|head|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137031 ns, free_ts 0 ns
PFN 530157 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137083 ns, free_ts 0 ns
PFN 530158 type Unmovable Block 517 type Unmovable Flags 0x4000000000000200(slab|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137135 ns, free_ts 0 ns
PFN 530159 type Unmovable Block 517 type Unmovable Flags 0x4000000000000200(slab|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137343 ns, free_ts 0 ns
PFN 530160 type Unmovable Block 517 type Unmovable Flags 0x4000000000010200(slab|head|zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137395 ns, free_ts 0 ns
PFN 530161 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137552 ns, free_ts 0 ns
PFN 530162 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137604 ns, free_ts 0 ns
PFN 530163 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137864 ns, free_ts 0 ns
PFN 530164 type Unmovable Block 517 type Unmovable Flags 0x4000000000000000(zone=1|kasantag=0x0)
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
page_owner.txt
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135260 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135468 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135624 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135781 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135833 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135885 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43135937 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136406 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136614 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136770 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136822 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43136979 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137031 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137083 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137135 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137343 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137395 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137552 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137604 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137864 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137916 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137916 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138124 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138177 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138229 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138281 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138333 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138541 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138749 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138802 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43138958 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139010 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139062 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139114 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139270 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139322 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139374 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139427 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139427 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139583 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139635 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139687 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139739 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139791 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139843 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139895 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139947 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139999 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43140052 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43140104 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
sorted_page_owner.txt
如下类似内容:
1 times:
Page allocated via order 9, mask 0x1521c2(__GFP_HIGHMEM|__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_ZERO|__GFP_HARDWALL), pid 2379, tgid 1603 (Preview_2), ts 128125282786 ns, free_ts 75571306063 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
qcom_extend_sys_heap_alloc_largest_available+0x2cc/0xa98 [qcom_dma_heaps]
system_qcom_sg_buffer_alloc+0xf4/0x380 [qcom_dma_heaps]
system_heap_allocate+0x90/0x168 [qcom_dma_heaps]
dma_heap_buffer_alloc+0x5c/0x6c
cam_mem_util_get_dma_buf+0x2c4/0x718 [camera]
cam_mem_mgr_alloc_and_map+0x284/0x7f8 [camera]
cam_private_ioctl+0x318/0x274c [camera]
__video_do_ioctl+0x298/0x4dc
video_usercopy+0x43c/0xb38
video_ioctl2+0x18/0x28
v4l2_ioctl+0x6c/0x84
__arm64_sys_ioctl+0xa8/0xe4
1 times:
Page allocated via order 0, mask 0x100dc0(GFP_USER|__GFP_ZERO), pid 14313, tgid 1603 (SyncThread), ts 128067784036 ns, free_ts 127389201898 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
qcom_io_pgtable_alloc_page+0xa0/0x1e8 [qcom_iommu_util]
__arm_lpae_alloc_pages+0x34/0x178 [qcom_iommu_util]
__arm_lpae_map+0x258/0x4fc [qcom_iommu_util]
__arm_lpae_map+0x4c4/0x4fc [qcom_iommu_util]
qcom_arm_lpae_map_pages+0xf4/0x168 [qcom_iommu_util]
arm_smmu_map_pages+0xd0/0x26c [arm_smmu]
__iommu_map+0x1d0/0x330
__iommu_map_sg+0xcc/0x1d4
iommu_map_sg+0x14/0x20
cam_smmu_map_buffer_validate+0x744/0x9c8 [camera]
cam_smmu_map_user_iova+0x31c/0x5b8 [camera]
cam_mem_util_map_hw_va+0x1c8/0x3b4 [camera]
1 times:
Page allocated via order 0, mask 0x100dc0(GFP_USER|__GFP_ZERO), pid 13119, tgid 30614 (SyncThread), ts 175393672508846 ns, free_ts 175393621807075 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
__get_free_pages+0x1c/0x50
__pte_alloc_kernel+0x24/0xe4
__vmap_pages_range_noflush+0x314/0x488
vmap+0xb8/0x148
qcom_sg_do_vmap+0x114/0x170 [qcom_dma_heaps]
qcom_sg_vmap+0x74/0xcc [qcom_dma_heaps]
dma_buf_vmap+0xc8/0x144
cam_compat_util_get_dmabuf_va+0x38/0xd8 [camera]
cam_mem_util_map_cpu_va+0x68/0x114 [camera]
cam_mem_mgr_alloc_and_map+0x588/0x7f8 [camera]
cam_private_ioctl+0x318/0x274c [camera]
__video_do_ioctl+0x298/0x4dc
2 times:
Page allocated via order 0, mask 0x112dc2(GFP_HIGHUSER|__GFP_NOWARN|__GFP_NORETRY|__GFP_ZERO), pid 2191, tgid 1772 (vppservice), ts 6585601582 ns, free_ts 0 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
__iommu_dma_alloc_noncontiguous+0x144/0x404
iommu_dma_alloc+0xa0/0x324
dma_alloc_attrs+0xd4/0x108
fastrpc_buf_alloc+0x1c4/0x4e4 [frpc_adsprpc]
fastrpc_internal_mmap+0x8c/0x26c [frpc_adsprpc]
fastrpc_device_ioctl+0x62c/0x24f4 [frpc_adsprpc]
__arm64_sys_ioctl+0xa8/0xe4
invoke_syscall+0x58/0x114
el0_svc_common+0xb4/0xfc
do_el0_svc+0x2c/0xb8
el0_svc+0x2c/0xa4
el0t_64_sync_handler+0x68/0xb4
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43137916 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43139427 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43140416 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43141718 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43142968 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43143177 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43144479 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43144687 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43145885 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43147239 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43148541 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43149999 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43151406 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43159427 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
2 times:
Page allocated via order 0, mask 0x0(), pid 1, tgid 1 (swapper/0), ts 43160729 ns, free_ts 0 ns
register_early_stack+0x34/0x78
init_page_owner+0x3c/0x2dc
page_ext_init+0x1c0/0x1d4
kernel_init_freeable+0xe8/0x158
分析
由于进程组的存在,堆栈信息会表现出多个pid指向同一个tgid,进程组ID是由进程组的首个进程的PID来确定的,这个进程被称为进程组的领头进程(也称为进程组长)
因此 pid 或者tgid为camera相关的对应堆栈都应被统计为camera内存
el0t_64_sync
invoke_syscall
__arm64_sys_ioctl
dma_heap_ioctl——ion的gralloc、cdsprpc、三方库
system_heap_allocate
dma_buf_ioctl
v4l2_ioctl——ion的cmdbuffer部分、CSLAlloc、ImageBuffer
video_ioctl2
video_usercopy
__video_do_ioctl
kgsl_ioctl——gpu申请
kgsl_ioctl_gpuobj_alloc
gpumem_alloc_entry
binder_ioctl
fastrpc_device_ioctl
dm_ctl_ioctl
security_file_ioctl
cvp_unblocked_ioctl——ion libeva.so
ashmem_ioctl
__arm64_sys_prctl
anon_vma_name_alloc
__arm64_sys_openat
do_sys_openat2
__arm64_sys_clone
kernel_clone
以ps -e|grepcamera.provider返回的14163为例,在pageowner中为进程组,多个tgid为14163的均为provider相关进程。
Page allocated via order 0, mask 0x102dc2(GFP_HIGHUSER|__GFP_NOWARN|__GFP_ZERO), pid 14163, tgid 14163 (binder:14163_2), ts 845516934762555 ns, free_ts 845516934432347 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
__alloc_pages_bulk+0x2f8/0x6a8
__vmalloc_node_range+0x564/0x808
dup_task_struct+0x1ac/0x3f8
copy_process+0x174/0xc3c
kernel_clone+0xb0/0x488
__arm64_sys_clone+0x5c/0x8c
invoke_syscall+0x58/0x114
el0_svc_common+0xb4/0xfc
do_el0_svc+0x2c/0xb8
el0_svc+0x2c/0xa4
el0t_64_sync_handler+0x68/0xb4
el0t_64_sync+0x1a0/0x1a4
2 times:
Page allocated via order 0, mask 0x112002(__GFP_HIGHMEM|__GFP_NOWARN|__GFP_NORETRY|__GFP_HARDWALL), pid 15290, tgid 14163 (vendor.qti.came), ts 845529549682750 ns, free_ts 845529494341708 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
kgsl_shmem_fill_page+0x1b4/0x39c [msm_kgsl]
__traceiter_android_rvh_shmem_get_folio+0x50/0x7c
shmem_alloc_and_acct_folio+0x30c/0x340
shmem_get_folio_gfp+0x2ec/0x998
shmem_read_mapping_page_gfp+0x5c/0xc8
_kgsl_alloc_pages+0x1cc/0x4c0 [msm_kgsl]
kgsl_allocate_user+0x190/0x320 [msm_kgsl]
gpumem_alloc_entry+0xfc/0x43c [msm_kgsl]
gen7_preemption_context_init+0x58/0x84 [msm_kgsl]
adreno_drawctxt_create+0x2c4/0x328 [msm_kgsl]
kgsl_ioctl_drawctxt_create+0x4c/0x134 [msm_kgsl]
kgsl_ioctl_helper+0x118/0x174 [msm_kgsl]
Charged to memcg provider
2 times:
Page allocated via order 0, mask 0x112002(__GFP_HIGHMEM|__GFP_NOWARN|__GFP_NORETRY|__GFP_HARDWALL), pid 15534, tgid 14163 (MiHalThd0), ts 845530108123325 ns, free_ts 845529497914052 ns
post_alloc_hook+0x1c0/0x208
prep_new_page+0x28/0x12c
get_page_from_freelist+0x1190/0x12b4
__alloc_pages+0x12c/0x2fc
kgsl_shmem_fill_page+0x1b4/0x39c [msm_kgsl]
__traceiter_android_rvh_shmem_get_folio+0x50/0x7c
shmem_alloc_and_acct_folio+0x30c/0x340
shmem_get_folio_gfp+0x2ec/0x998
shmem_read_mapping_page_gfp+0x5c/0xc8
_kgsl_alloc_pages+0x1cc/0x4c0 [msm_kgsl]
kgsl_allocate_user+0x190/0x320 [msm_kgsl]
gpumem_alloc_entry+0xfc/0x43c [msm_kgsl]
kgsl_ioctl_gpuobj_alloc+0x1c/0xe8 [msm_kgsl]
kgsl_ioctl_helper+0x118/0x174 [msm_kgsl]
kgsl_ioctl+0x34/0x9c [msm_kgsl]
__arm64_sys_ioctl+0xa8/0xe4
Charged to memcg provider
相关pidname介绍:
kworker:负责处理各种内核任务
kswapd:定期扫描系统中的内存页面,将不常用的页面交换到磁盘上,以释放内存空间
vppservice:视频处理相关的任务,例如视频编解码、视频旋转、视频缩放、视频色彩空间转换等
binder:进程间通信进程
AlgoFwkThd
MiHalThd
SyncThread:统服务进程中的一个线程,负责处理与账户同步相关的任务
camera-saver
modprobe:加载和卸载内核模块
CamXBITMLInit:初始化相机硬件和相机驱动程序
Malloc
malloc是用户态函数,申请的是虚拟内存,此时MMU并没有创建虚拟页物理页映射关系。只有当发生缺页异常时才会向内核发出缺页中断去申请物理内存。当malloc一次性能申请小内存(小于128KB),分配的是在堆区(heap),用sbrk()进行对齐生长,而malloc一次性申请大内存(大于128KB时)分配到的是在映射区,而不是在堆区,采用的mmap()系统调用进行映射。
缺页异常的产生原因
缺页异常是在通过虚拟地址去访问物理内存的过程中出现失败时抛出的异常,访问的过程包括几个阶段,首先是通过虚拟地址访问页表转换为物理地址,第二个阶段是通过物理地址访问物理内存,而错误的原因有以下几种:
- 第一个阶段出现错误,通过MMU将虚拟地址转换为物理地址时发现 不存在映射关系
- 第二个阶段出错,通过物理地址访问内存,发现 page不在内存当中
- 第二个阶段出错,通过物理地址访问内存,发现 权限错误
mmap内核态实现函数: ksys_mmap_pgoff
unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
struct file *file = NULL;
unsigned long retval;
// 预处理文件映射
if (!(flags & MAP_ANONYMOUS)) {
// 根据 fd 获取映射文件的 struct file 结构
audit_mmap_fd(fd, flags);
file = fget(fd);
if (!file)
// 这里可以看出如果是匿名映射的话必须要指定 MAP_ANONYMOUS 否则这里就返回错误了
return -EBADF;
// 映射文件是否是 hugetlbfs 中的文件,hugetlbfs 中的文件默认由大页支持
if (is_file_hugepages(file))
// mmap 进行文件大页映射,len 需要和大页尺寸对齐
len = ALIGN(len, huge_page_size(hstate_file(file)));
retval = -EINVAL;
// 这里可以看出如果想要使用 mmap 对文件进行大页映射,那么映射的文件必须是 hugetlbfs 中的
// mmap 文件大页映射并不需要指定 MAP_HUGETLB,并且 mmap 不能对普通文件进行大页映射
if (unlikely(flags & MAP_HUGETLB && !is_file_hugepages(file)))
goto out_fput;
} else if (flags & MAP_HUGETLB) {
// 从这里我们可以看出 MAP_HUGETLB 只能支持 MAP_ANONYMOUS 匿名映射的方式使用 HugePage
struct user_struct *user = NULL;
// 内核中的大页池(预先创建)
struct hstate *hs;
// 选取指定大页尺寸的大页池(内核中存在不同尺寸的大页池)
hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
if (!hs)
return -EINVAL;
// 映射长度 len 必须与大页尺寸对齐
len = ALIGN(len, huge_page_size(hs));
// 在 hugetlbfs 中创建 anon_hugepage 文件,并预留大页内存(禁止其他进程申请)
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len,
VM_NORESERVE,
&user, HUGETLB_ANONHUGE_INODE,
(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
if (IS_ERR(file))
return PTR_ERR(file);
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
// 开始内存映射
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
out_fput:
if (file)
// file 引用计数减 1
fput(file);
return retval;
}
相关函数接口与堆栈
do_page_fault——缺页中断处理函数arch/arm/mm/fault.c
handle_mm_fault
ksys_mmap_pgoff——malloc mmap的内核函数
vm_mmap_pgoff
do_mmap
mmap_region
__arm64_sys_mremap——重新映射一个虚拟内存区域
move_vma
copy_vma
__arm64_sys_munmap——解除映射一个虚拟内存区域
__vm_munmap
do_mas_align_munmap
Dmabuf
申请一个buffer,再创建一个dmabuf 结构体然后将,然后将dmabuf中得指针指向buffer,dmabuf 再传递给一个匿名的inode,获取到一个file,这样file和dmabuf绑定起来,也就和buffer关联上。然后再从进程中分配一个空闲的fd,将fd和file绑定。这样就能通过fd 快速查找到buffer。file 是个全系统的,他和进程无关,但是fd 是每个进程都是自己独立的,所以再跨进程传输时只需要保证fd 和同一个file绑定就可以实现buffer的共享。
相关函数接口与堆栈
/*/mivendor_u_sm8650/kernel_platform/msm-kernel/drivers/dma-buf/*/
dma_heap_ioctl——gralloc、cdsprpc、三方库
system_heap_allocate
/*/mivendor_u_sm8650/vendor/qcom/opensource/camera-kernel/drivers/cam_req_mgr/*/
v4l2_ioctl——cmdbuffer、CSLAlloc、ImageBuffer
video_ioctl2
video_usercopy
__video_do_ioctl
cam_private_ioctl
cam_mem_mgr_alloc_and_map
cam_mem_util_get_dma_buf
dma_heap_buffer_alloc
system_heap_allocate
/*/mivendor_u_sm8650/vendor/qcom/opensource/eva-kernel/msm/eva/msm_cvp_ioctl.c*/
cvp_unblocked_ioctl——libeva.so
cvp_ioctl
msm_cvp_private
msm_cvp_handle_syscall
msm_cvp_session_create
cvp_comm_set_arp_buffers
cvp_allocate_arp_bufs
msm_cvp_smem_alloc
dma_heap_buffer_alloc
system_heap_allocate
然而在pageowner中使用以上接口过滤出的内存占用远低于实际能够统计到的dmabuf,这是因为以上接口申请的是虚拟内存:
static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
{
struct qcom_sg_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
int ret;
//申请的是虚拟内存
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
if (!buffer)
return ERR_PTR(-ENOMEM);
ret = system_qcom_sg_buffer_alloc(heap, buffer, len, false);
if (ret)
goto free_buf_struct;
buffer->vmperm = mem_buf_vmperm_alloc(&buffer->sg_table);
if (IS_ERR(buffer->vmperm)) {
ret = PTR_ERR(buffer->vmperm);
goto free_sys_heap_mem;
}
/* create the dmabuf */
exp_info.exp_name = dma_heap_get_name(heap);
exp_info.size = buffer->len;
exp_info.flags = fd_flags;
exp_info.priv = buffer;
dmabuf = qcom_dma_buf_export(&exp_info, &qcom_sg_buf_ops);
if (IS_ERR(dmabuf)) {
ret = PTR_ERR(dmabuf);
goto free_vmperm;
}
return dmabuf;
free_vmperm:
mem_buf_vmperm_release(buffer->vmperm);
free_sys_heap_mem:
qcom_system_heap_free(buffer);
return ERR_PTR(ret);
free_buf_struct:
kfree(buffer);
return ERR_PTR(ret);
}
以v4l2_ioctl申请imagebuffer为例:
CamxResult ImageBufferManager::InitializeBuffers(
BufferManagerCreateData* pCreateData)
{
ImageBuffer* pBuffer = CAMX_NEW ImageBuffer();
CAMX_ASSERT(NULL != pBuffer);
if (NULL != pBuffer)
{
result = pBuffer->Initialize(m_pBufferManagerName, &m_createData, &m_currentFormat, this,
m_hMemPoolBufMgrHandle);
if (CamxResultSuccess != result)
{
CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] : Failed in initializing ImageBuffer object, result=%s",
GetBufferManagerName(), Utils::CamxResultToString(result));
}
}
// Allocate the buffer
result = pBuffer->Allocate();
CAMX_ASSERT(CamxResultSuccess == result);\
if (CamxResultSuccess == result)
{
LDLLNode* pNode = static_cast<LDLLNode*>(CAMX_CALLOC(sizeof(LDLLNode)));
if (NULL != pNode)
{
pNode->pData = pBuffer;
// Add the buffer to the free buffer list
m_freeBufferList.InsertToTail(pNode);
CAMX_LOG_VERBOSE(CamxLogGroupMemMgr, "[%s] ImageBuffer %p", GetBufferManagerName(), pBuffer);
}
else
{
CAMX_LOG_ERROR(CamxLogGroupMemMgr, "[%s] : Failed in allocating Node", GetBufferManagerName());
result = CamxResultENoMemory;
}
}
}
申请的虚拟内存的dmabuf存储在了m_freeBufferList,使用的时候:
IImageBuffer* ImageBufferManager::GetImageBuffer()
{
LDLLNode* pNode = m_freeBufferList.RemoveFromHead();
pBuffer = static_cast<ImageBuffer*>(pNode->pData);
CAMX_FREE(pNode);
pNode = NULL;
}
实际修改使用dmabuf的例子:
/// @brief Defines the image buffer.
chicommon.h
typedef struct /** @cond */ ChiImage /** @endcond */
{
UINT32 size; ///< Size of the structure.
INT fd[ChiNodeFormatsMaxPlanes]; ///< Maps the buffer to the file descriptor.
UCHAR* pAddr[ChiNodeFormatsMaxPlanes]; ///< Pointer to the starting virtual address of the allocated
/// buffer.
CHIHANDLE pNativeHandle; ///< Pointer to the native handle.
} CHIIMAGE;
camxchinodesat.cpp
SatImage ChiSATNode::CvtHandle2Image(CHINODEBUFFERHANDLE hInput)
{
SatImage::ImageType imageType;
SatImage::DataType dataType;
if (hInput->format.format == P010)
{
imageType = SatImage::IMAGETYPE_P010;
dataType = SatImage::DT_16U;
}
else if (hInput->format.format == YUV420NV12)
{
imageType = SatImage::IMAGETYPE_NV12;
dataType = SatImage::DT_8U;
}
else if (hInput->format.format == YUV420NV21)
{
imageType = SatImage::IMAGETYPE_NV21;
dataType = SatImage::DT_8U;
}
else if (hInput->format.format == UBWCTP10)
{
imageType = SatImage::IMAGETYPE_UBWC_TP10;
dataType = SatImage::DT_16U;
}
else
{
imageType = SatImage::IMAGETYPE_MAX;
dataType = SatImage::DT_8U;
MEGVII_LOG_ERROR("unsupported image format: %d", hInput->format.format);
}
MEGVII_LOG_VERBOSE("[MEGVII_SAT] image type: %d", hInput->format.format);
int width = hInput->format.width;
int height = hInput->format.height;
int stride = hInput->format.formatParams.yuvFormat[0].planeStride;
int slice_height = hInput->format.formatParams.yuvFormat[0].sliceHeight;
if (imageType == SatImage::IMAGETYPE_P010)
{
stride /= 2;
}
SatImage image(stride, slice_height,
hInput->pImageList[0].pAddr[0],
hInput->pImageList[0].pAddr[1],
NULL,
imageType,
dataType,
SatImage::ROTATION_0);
image.setImageWH(width, height);
int imageFd[] = {hInput->pImageList[0].fd[0], hInput->pImageList[0].fd[1]};
image.setIonFd(imageFd, sizeof(imageFd) / sizeof(int));
return image;
}
最终以fd指定dmabuf进程操作,因此pageowner中write、read相关的文件操作可能与dmabuf相关。在读写过程中申请物理内存
相关函数接口与堆栈
__arm64_sys_write——写文件时缺页出现的内存申请
ksys_write
vfs_write
__folio_alloc
__arm64_sys_read
ksys_read
vfs_read
f2fs_file_read_iter
proc_reg_read
do_read_cache_folio
do_writev——在文件上执行写操作
do_iter_write
sock_write_iter
user_path_at_empty——通过文件系统进行文件操作,中途需要添加page
filename_lookup
path_lookupat
walk_component
lookup_slow
__lookup_slow
binder_ioctl——读写时候申请的实际物理内存
binder_ioctl_write_read
gpu
/vendor/qcom/opensource/graphics-kernel/
相关函数接口与堆栈
kgsl_mem_alloc
kgsl_ioctl_helper
kgsl_ioctl_gpuobj_alloc
gpumem_alloc_entry
kgsl_mem_map
kgsl_ioctl_helper
kgsl_ioctl_gpuobj_import
其他能够被统计到的堆栈信息
copy_process:创建进程
__arm64_sys_mprotect——修改内存页属性。设置vma的读写属性和映射方式
mprotect_fixup
__arm64_sys_execve:用于执行一个新的程序。当该函数被调用时,它会将当前进程的上下文切换到一个新的程序中,新程序的代码将会替换当前进程的代码,并开始执行
v4l2_ioctl
video_ioctl2
video_usercopy
__video_do_ioctl
v4l_subscribe_event
cam_subscribe_event
try_to_free_pages——zram压缩申请的内存
__arm64_sys_prctl——系统调用,用于修改进程的属性
anon_vma_name_alloc
当前统计不到的关键字
fastrpc_device_ioctl:cdsp的软件接口申请的内存
__arm64_sys_openat:用于打开文件
do_sys_openat2
do_filp_open
path_openat
vfs_open
do_dentry_open
chrdev_open
v4l2_open
kernel_init_freeable
cam_icp_subdev_open
cam_icp_mgr_hw_open_u
cam_icp_mgr_hw_open
v4l2_ioctl
subdev_ioctl
video_usercopy
subdev_do_ioctl_lock
cam_eeprom_subdev_ioctl
cam_eeprom_driver_cmd
cam_compat_util_get_dmabuf_va
dma_buf_vmap
qcom_sg_vmap
qcom_sg_do_vmap
cam_eeprom_driver_cmd——camera驱动自己申请的内存。摄像头驱动程序需要分配内存来初始化pinctrl、传感器核心和EEPROM
cam_sensor_driver_cmd
cam_ois_driver_cmd
参考
brk系统调用:https://zhuanlan.zhihu.com/p/579405096
小结
- Make sure following parameters in cmdline:
page_pinner=1 stack_depot_disable=off page_owner=on
- Make sure following configs enabled:
CONFIG_PAGE_PINNER=y
CONFIG_CMA_DEBUG=y
CONFIG_PAGE_OWNER=y
When issue happened, trigger dump, then parse dump by ramparser with following parameters:
–slabinfo –slabsummary –print-pagetracking
后续总结一下更多关于 page_owner的实战内容。