解析进程 /proc/pid/maps 和 /proc/pid/smaps

目录

/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表,下一个vma;vma表,上一个vma
 
    struct 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_struct
    pgprot_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 file's 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_SWAP
    atomic_long_t swap_readahead_info;
#endif
#ifndef CONFIG_MMU
    struct vm_region *vm_region;    /* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
    struct mempolicy *vm_policy;    /* NUMA policy for the VMA */
#endif
    struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
    seqcount_t vm_sequence;
    atomic_t vm_ref_count;      /* see vma_get(), vma_put() */
#endif
    ANDROID_KABI_RESERVE(1);
    ANDROID_KABI_RESERVE(2);
    ANDROID_KABI_RESERVE(3);
    ANDROID_KABI_RESERVE(4);
    ANDROID_VENDOR_DATA(1);
} __randomize_lay
回答: /proc/2042/smaps是一个特殊的文件,它提供了关于进程2042的虚拟内存映射的详细信息。当我们执行cat /proc/2042/smaps时,实际上是在读取该进程对应的虚拟内存区间的信息。这个过程涉及到两个主要步骤:open()read()。首先,用户态的open("/proc/2042/smaps")函数会陷入内核,通过/proc/2042/smaps文件相关的inode来找到进程2042的相关信息,并将这些信息搜集到proc_maps_private结构中。然后,open()函数将proc_maps_private结构smaps文件的具体操作函数结构放到file->private_data中,并返回smaps文件对应的文件描述符fd。接下来,用户态的read(fd)函数通过传入的文件描述符fd找到之前open()函数准备好的file结构,并进行读取操作,将文件内容显示给我们。\[1\]\[2\]所以,执行cat /proc/2042/smaps实际上是通过open()read()函数来读取进程2042的虚拟内存映射信息。\[1\]\[2\] #### 引用[.reference_title] - *1* *2* [cat /proc/$pid/smaps浅析(一)](https://blog.csdn.net/wennuanddianbo/article/details/96473862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Linux内存管理 -- /proc/{pid}/smaps讲解](https://blog.csdn.net/armlinuxww/article/details/109022698)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值