天津免费建设网站,网络营销的特点是什么?,营销推广活动策划,网站建设+备案什么意思目录
/proc//maps
背景
具体描述
代码实现
实践
/proc/pid/smaps
smaps各子项详解
代码实现
代码调用的路径如下#xff1a;
小结 /proc/pid/maps
背景
相对于/proc/meminfo和dumpsys meminfo可以看到系统整体的内存信息#xff0c;我们还需要能够具体到…
目录
/proc//maps
背景
具体描述
代码实现
实践
/proc/pid/smaps
smaps各子项详解
代码实现
代码调用的路径如下
小结 /proc/pid/maps
背景
相对于/proc/meminfo和dumpsys meminfo可以看到系统整体的内存信息我们还需要能够具体到每一个进程内存占用统计的信息。
在分析内存问题的时候会经常依赖kernel的proc文件系统下各个进程的文件节点从中获取当前进程的详细内存信息今天就来简单介绍一下比较常用的一个节点/proc/pid/maps
Proc/pid/maps显示进程映射了的内存区域和访问权限。对应内核中的操作集为proc_pid_maps_op具体的导出函数为show_map
内核中进程的一段地址空间用一个vm_area_struct结构体表示所有地址空间存储在 struct task_struct - struct mm_struct - mmap链表中。 具体描述
如下为一个vm_area_struct结构体的描述详解描述了一个虚拟内存区域的信息。
vm_area_struct
struct vm_area_struct {/* The first cache line has the info for VMA tree walking. */unsigned long vm_start; /* Our start address within vm_mm. */ //区域的首地址unsigned long vm_end; /* The first byte after our end address within vm_mm. */ //区域的尾地址/* linked list of VM areas per task, sorted by address *///该vma在一个进程的vma链表中的前驱vma和后驱vma指针链表中的vma都是按地址来排序的struct vm_area_struct *vm_next, *vm_prev; //vma表下一个vmavma表上一个vmastruct rb_node vm_rb; //红黑树中对应的节点/** Largest free memory gap in bytes to the left of this VMA.* Either between this VMA and vma-vm_prev, or between one of the* VMAs below us in the VMA rbtree and its -vm_prev. This helps* get_unmapped_area find a free area of the right size.*/unsigned long rb_subtree_gap;/* Second cache line starts here. */struct mm_struct *vm_mm; /* The address space we belong to. */ // 所属的内存描述符,vma属于哪个mm_structpgprot_t vm_page_prot; /* Access permissions of this VMA. */ //vma的访问权限unsigned long vm_flags; /* Flags, see mm.h. */ /** For areas with an address space and backing store,* linkage into the address_space-i_mmap interval tree.** For private anonymous mappings, a pointer to a null terminated string* in the user process containing the name given to the vma, or NULL* if unnamed.*///shared联合体用于和address space关联union {struct {struct rb_node rb;unsigned long rb_subtree_last;} shared;const char __user *anon_name;};/** A files MAP_PRIVATE vma can be in both i_mmap tree and anon_vma* list, after a COW of one of the file pages. A MAP_SHARED vma* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack* or brk vma (with NULL file) can only be in an anon_vma list.*//*anno_vma_chain和annon_vma用于管理源自匿名映射的共享页*/struct list_head anon_vma_chain; /* Serialized by mmap_sem * page_table_lock */ struct anon_vma *anon_vma; /* Serialized by page_table_lock */ //指向匿名域的指针/*该vma上的各种标准操作函数指针集*/const struct vm_operations_struct *vm_ops;/* Information about our backing store: */unsigned long vm_pgoff; /* 映射文件的偏移量以PAGE_SIZE为单位 */struct file * vm_file; /* 映射的文件没有则为NULL;可以通过这个区分匿名页和文件页*/void * vm_private_data; /* was vm_pte (shared mem) */#ifdef CONFIG_SWAPatomic_long_t swap_readahead_info;
#endif
#ifndef CONFIG_MMUstruct vm_region *vm_region; /* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMAstruct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endifstruct vm_userfaultfd_ctx vm_userfaultfd_ctx;
#ifdef CONFIG_SPECULATIVE_PAGE_FAULTseqcount_t vm_sequence;atomic_t vm_ref_count; /* see vma_get(), vma_put() */
#endifANDROID_KABI_RESERVE(1);ANDROID_KABI_RESERVE(2);ANDROID_KABI_RESERVE(3);ANDROID_KABI_RESERVE(4);ANDROID_VENDOR_DATA(1);
} __randomize_layout;
下表为每一个用vm_area_struct描述的内存区域的具体信息表格第一列的字段对应上面vm_area_struct结构体内部的一些成员。 vm_start “-”前一列如00377000 此段虚拟地址空间起始地址 vm_pgoff 第四列如00000000 对有名映射表示此段虚拟内存起始地址在文件中以页为单位的偏移。对匿名映射它等于0或者vm_start/PAGE_SIZE vm_flags 第三列如r-xp 此段虚拟地址空间的属性。每种属性用一个字段表示r表示可读w表示可写x表示可执行p和s共用一个字段互斥关系p表示私有段s表示共享段如果没有相应权限则用’-’代替 vm_file-f_dentry-d_inode-i_sb-s_dev 第五列如fd:00 映射文件所属设备号。对匿名映射来说因为没有文件在磁盘上所以没有设备号始终为00:00。对有名映射来说是映射的文件所在设备的设备号 vm_file-f_dentry-d_inode-i_ino 第六列如9176473 映射文件所属节点号。对匿名映射来说因为没有文件在磁盘上所以没有节点号始终为00:00。对有名映射来说是映射的文件的节点号 vm_end “-”后一列如00390000 此段虚拟地址空间结束地址 第七列如/system/bin/init 对有名来说是映射的文件名。对匿名映射来说是此段虚拟内存在进程中的角色。[stack]表示在进程中作为栈使用[heap]表示堆。其余情况则无显示 具体的/proc/pid/maps文件实例
vm_start -vm_end vm_flags vm_pgoff f_entry 映射的文件名/虚拟内存的作用
5567882000-55678b2000 r--p 00000000 fd:06 564 /system/bin/init
55678b2000-556797b000 r-xp 00030000 fd:06 564 /system/bin/init
556797b000-556797f000 r--p 000f9000 fd:06 564 /system/bin/init
556797f000-5567980000 rw-p 000fc000 fd:06 564 /system/bin/init
5567980000-5567981000 rw-p 00000000 00:00 0 [heap] //映射到堆
7f14800000-7f14c00000 rw-p 00000000 00:00 0 [anon:libc_malloc]
7f14d22000-7f14d24000 rw-p 00000000 00:00 0
7f14d24000-7f15d22000 ---p 00000000 00:00 0
7f15d22000-7f15d23000 ---p 00000000 00:00 0
7f15d23000-7f15e1f000 rw-p 00000000 00:00 0 [anon:stack_and_tls:508]
7f15e1f000-7f15e20000 ---p 00000000 00:00 0
7f15e20000-7f15e40000 rw-s 00000000 00:12 9778 /dev/__properties__/properties_serial
7f15e40000-7f15e60000 rw-s 00000000 00:12 9777 /dev/__properties__/u:object_r:wifi_prop:s0
7f15e60000-7f15e80000 rw-s 00000000 00:12 9776 /dev/__properties__/u:object_r:wifi_log_prop:s0
7f15e80000-7f15ea0000 rw-s 00000000 00:12 9775 /dev/__properties__/u:object_r:vold_prop:s0
7f15ea0000-7f15ec0000 rw-s 00000000 00:12 9774 /dev/__properties__/u:object_r:vndk_prop:s0
7f15ec0000-7f15ee0000 rw-s 00000000 00:12 9773 /dev/__properties__/u:object_r:virtual_ab_prop:s0
7f15ee0000-7f15f00000 rw-s 00000000 00:12 9772 /dev/__properties__/u:object_r:vendor_zygote_disable_gl_preload:s0
7f15f00000-7f15f20000 rw-s 00000000 00:12 9771 /dev/__properties__/u:object_r:vendor_wifienhancelog_prop:s0
7f15f20000-7f15f40000 rw-s 00000000 00:12 9770 /dev/__properties__/u:object_r:vendor_touchfeature_prop:s0
7f15f40000-7f15f60000 rw-s 00000000 00:12 9769 /dev/__properties__/u:object_r:vendor_thermal_normal_prop:s0
7f15f60000-7f15f80000 rw-s 00000000 00:12 9768 /dev/__properties__/u:object_r:vendor_socket_hook_prop:s0
7f15f80000-7f15fa0000 rw-s 00000000 00:12 9767 /dev/__properties__/u:object_r:vendor_slad_prop:s0
7f15fa0000-7f15fc0000 rw-s 00000000 00:12 9766 /dev/__properties__/u:object_r:vendor_security_patch_level_prop:s0
7f15fc0000-7f15fe0000 rw-s 00000000 00:12 9765 /dev/__properties__/u:object_r:vendor_ro_audio_prop:s0
7f15fe0000-7f16000000 rw-s 00000000 00:12 9764 /dev/__properties__/u:object_r:vendor_payment_security_prop:s0
7f16000000-7f16020000 rw-s 00000000 00:12 9763 /dev/__properties__/u:object_r:vendor_panel_info_prop:s0
7f16020000-7f16040000 rw-s 00000000 00:12 9762 /dev/__properties__/u:object_r:vendor_mtkcam_prop:s0 代码实现
///proc/pid/maps节点的操作集seq_operations序列操作
static const struct seq_operations proc_pid_maps_op {.start m_start,.next m_next,.stop m_stop,.show show_map
};
show_map()
| |-show_map_vma()
| | |-file_inode()
| | |-show_vma_header_prefix()
| | | |-seq_file操作遍历VMA的信息
| | |-arch_vma_name() 实践
编写能够可视化maps文件的工具
https://www.cnblogs.com/arnoldlu/p/10272466.html /proc/pid/smaps
/proc/PID/smaps 文件是基于 /proc/PID/maps 的扩展他展示了一个进程的内存消耗比同一目录下的maps文件更为详细。
smaps文件能够将maps文件中展示的所有vma内存区都进行详细统计输出更为详细的数据
在maps文件中只会输出每一个vma内存区域的起始/结束地址属性偏移量主从设备号以及映射问文件等等如下所示
5567882000-55678b2000 r--p 00000000 fd:06 564 /system/bin/init
55678b2000-556797b000 r-xp 00030000 fd:06 564 /system/bin/init
556797b000-556797f000 r--p 000f9000 fd:06 564 /system/bin/init
556797f000-5567980000 rw-p 000fc000 fd:06 564 /system/bin/init
5567980000-5567981000 rw-p 00000000 00:00 0 [heap]
7f14800000-7f14c00000 rw-p 00000000 00:00 0 [anon:libc_malloc]
7f14d22000-7f14d24000 rw-p 00000000 00:00 0
7f14d24000-7f15d22000 ---p 00000000 00:00 0
7f15d22000-7f15d23000 ---p 00000000 00:00 0
7f15d23000-7f15e1f000 rw-p 00000000 00:00 0 [anon:stack_and_tls:508]
7f15e1f000-7f15e20000 ---p 00000000 00:00 0
7f15e20000-7f15e40000 rw-s 00000000 00:12 9778 /dev/__properties__/properties_serial
7f15e40000-7f15e60000 rw-s 00000000 00:12 9777 /dev/__properties__/u:object_r:wifi_prop:s0
7f15e60000-7f15e80000 rw-s 00000000 00:12 9776 /dev/__properties__/u:object_r:wifi_log_prop:s0
7f15e80000-7f15ea0000 rw-s 00000000 00:12 9775 /dev/__properties__/u:object_r:vold_prop:s0
7f15ea0000-7f15ec0000 rw-s 00000000 00:12 9774 /dev/__properties__/u:object_r:vndk_prop:s0
7f15ec0000-7f15ee0000 rw-s 00000000 00:12 9773 /dev/__properties__/u:object_r:virtual_ab_prop:s0
7f15ee0000-7f15f00000 rw-s 00000000 00:12 9772 /dev/__properties__/u:object_r:vendor_zygote_disable_gl_preload:s0
7f15f00000-7f15f20000 rw-s 00000000 00:12 9771 /dev/__properties__/u:object_r:vendor_wifienhancelog_prop:s0 但是smaps文件能够给每一个vma内存区域进行统计在maps的基础上进行集成统计显示的信息更加详细和直观
5567882000-55678b2000 r--p 00000000 fd:06 564 /system/bin/init //对应maps中的第一个vma内存区域
Size: 192 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 64 kB
Pss: 42 kB
Shared_Clean: 44 kB
Shared_Dirty: 0 kB
Private_Clean: 20 kB
Private_Dirty: 0 kB
Referenced: 64 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
VmFlags: rd mr mw me dw
55678b2000-556797b000 r-xp 00030000 fd:06 564 /system/bin/init //对于maps文件中的第二个vma内存区域
Size: 804 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 356 kB
Pss: 261 kB
Shared_Clean: 148 kB
Shared_Dirty: 0 kB
Private_Clean: 208 kB
Private_Dirty: 0 kB
Referenced: 356 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
VmFlags: rd ex mr mw me dw smaps各子项详解
2.1 Size虚拟内存空间大小。但是这个内存值不一定是物理内存实际分配的大小因为在用户态上虚拟内存总是延迟分配的。这个值计算也非常简单就是该VMA的开始位置减结束位置。 延迟分配就是当进程申请内存的时候Linux会给他先分配页但是并不会区建立页与页框的映射关系意思就是说并不会分配物理内存而当真正使用的时候就会产生一个缺页异常硬件跳转page fault处理程序执行在其中分配物理内存然后修改页表(创建页表项)。异 常处理完毕返回程序用户态继续执行。
2.2 Rss是实际分配的内存这部分物理内存已经分配不需要缺页中断就可以使用的。 这里有一个公式计算RssRssShared_CleanShared_DirtyPrivate_CleanPrivate_Dirty
share/private该页面是共享还是私有。 dirty/clean该页面是否被修改过如果修改过dirty在页面被淘汰的时候就会把该脏页面回写到交换分区换出swap out。有一个标志位用于表示页面是否dirty。
share/private_dirty/clean 计算逻辑 查看该page的引用数如果引用1则归为shared如果是1则归为private同时也查看该page的flag是否标记为_PAGE_DIRTY如果不是则认为干净的。
2.3 Pssproportional set size是平摊计算后的实际物理使用内存(有些内存会和其他进程共享例如mmap进来的)。实际上包含下面private_cleanprivate_dirty和按比例均分的shared_clean、shared_dirty。
举个计算Pss的例子 如果进程A有x个private_clean页面有y个private_dirty页面有z个shared_clean仅和进程B共享有h个shared_dirty页面和进程B、C共享。那么进程A的Pss为x y z/2 h/3
2.4 Referenced当前页面被标记为已引用或者包含匿名映射The amount of memory currently marked as referenced or a mapping associated with a file may contain anonymous pages。
在Linux内存管理的页面替换算法里讲过当某个页面被访问后Referenced标志被设置如果该标志设置了就 不能将该页移出。
2.5 Anonymous匿名映射的物理内存这部分内存不来自于文件的内存大小。
2.6 ShmemPmdMappedPMD页面已经被映射的共享shmem / tmpfs内存量。在官方文档中这样解释ShmemPmdMapped shows the ammount of shared (shmem/tmpfs) memory backed by huge pages.
2.7 Shared/Private_Hugetlb由hugetlbfs页面支持的内存使用量由于历史原因该页面未计入“ RSS”或“ PSS”字段中。 并且这些没有包含在Shared/Private_Clean/Dirty 字段中。
2.8 Swap存在于交换分区的数据大小(如果物理内存有限可能存在一部分在主存一部分在交换分区)
2.9 SwapPss这个我并没有找到对应解释但从源码可以得知计算逻辑就跟pss一样只不过针对的是交换分区的内存。
2.10 KernelPageSize内核一页的大小2.11 MMUPageSizeMMU页大小大多数情况下和KernelPageSize大小一样。
2.12 Locked常驻物理内存的大小这些页不会被换出。相当于被锁住在物理内存中
2.13 THPeligible映射是否符合分配THP的条件。如果为true则为1否则为0。 它仅显示当前状态。
THP透明大页Transparent Huge PagesRHEL 6 开始引入目的是使用更大的内存页面memory page size 以适应越来越大的系统内存让操作系统可以支持现代硬件架构的大页面容量功能。与标准大页的区别在于分配机制标准大页管理是预分配的方式而透明大页管理则是动态分配的方式。
2.14 VmFlags表示与特定虚拟内存区域关联的内核标志。 VmFlags //VmFlags标志详解
rd - readable
wr - writeable
ex - executable
sh - shared
mr - may read
mw - may write
me - may execute
ms - may share
gd - stack segment growns down
pf - pure PFN range
dw - disabled write to the mapped file
lo - pages are locked in memory
io - memory mapped I/O area
sr - sequential read advise provided
rr - random read advise provided
dc - do not copy area on fork
de - do not expand area on remapping
ac - area is accountable
nr - swap space is not reserved for the area
ht - area uses huge tlb pages
ar - architecture specific flag
dd - do not include area into core dump
sd - soft-dirty flag
mm - mixed map area
hg - huge page advise flag
nh - no-huge page advise flag
mg - mergable advise flag 代码实现
5567882000-55678b2000 r--p 00000000 fd:06 564 /system/bin/init //----------------------------------------------show_map_vma()//----------------------------------------------__show_smap()
Size: 192 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 64 kB
Pss: 42 kB
Shared_Clean: 44 kB
Shared_Dirty: 0 kB
Private_Clean: 20 kB
Private_Dirty: 0 kB
Referenced: 64 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
VmFlags: rd mr mw me dw //---------------------------------------------show_smap_vma_flags() 代码调用的路径如下
show_smap()|-smap_gather_stats //最重要的获取信息渠道遍历vma下的所有page并且找到他们的物理页判断属于什么页| |-mss-swap shmem_swapped;| |-walk_page_vma| | |-walk_p4d_range -| | | |-walk_pud_range -| | | | |-walk_pmd_range - //因为这里只设置了pmd的回调所以只会执行到 walk-pmd_entry(pmd, addr, next, walk);不会执行到pte_entry()| | | | | -walk_pte_range - pte_entry()|-show_map_vma| |-vma_get_anon_name|-__show_smap|-show_smap_vma_flags 小结
后续总结更多代码实现细节。