内存管理-31-每进程内存统计-2-/proc/pid/statm

基于msm-5.4

一、初探

1. 打印格式

# cat /proc/593/statm //非内核线程
2826695 22403 17848 1420 0 12717 0 //以 PAGE_SIZE 为单位

# cat /proc/187/statm //内核线程
0 0 0 0 0 0 0

打印成员介绍:

1: size: 打印的是 mm->total_vm 的值,表示任务占用虚拟地址空间大小,单位PAGE_SZIE。对应status文件节点的 VmSize 除以4后的值。
2: resident: 打印的是 MM_FILEPAGES + MM_SHMEMPAGES + MM_ANONPAGES, 表示任务正在使用的物理内存的大小,对应status文件节点的 VmRSS 除以4后的值。
3: shared: 打印的是 MM_FILEPAGES + MM_SHMEMPAGES,表示任务的共享页数。
4: text: 任务代码段虚拟内存大小,打印的是 mm->end_code - mm->start_code 对应的页面个数,对应status文件节点的 VmExe 除以4后的值。
5: 打印的是固定0值
6: data: 打印的是 mm->data_vm + mm->stack_vm 的值。
7: 打印的是固定0值


2. 实现

static const struct pid_entry tgid_base_stuff[] = { //fs/proc/base.c
    ONE("statm",      S_IRUGO, proc_pid_statm),
};
static const struct pid_entry tid_base_stuff[] = { //fs/proc/base.c
    ONE("statm",     S_IRUGO, proc_pid_statm),
};

int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
        struct pid *pid, struct task_struct *task) //proc/array.c
{
    unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
    /* 若是内核线程返回NULL */
    struct mm_struct *mm = get_task_mm(task);
    if (mm) {
        size = task_statm(mm, &shared, &text, &data, &resident);
        mmput(mm);
    }
    seq_printf(m, "%lu %lu %lu %lu 0 %lu 0\n", size, resident, shared, text, data);

    return 0;
}

unsigned long task_statm(struct mm_struct *mm, unsigned long *shared, unsigned long *text,
        unsigned long *data, unsigned long *resident) //proc/task_mmu.c
{
    /* mm->rss_stat.count[MM_FILEPAGES] + mm->rss_stat.count[MM_SHMEMPAGES] */
    *shared = get_mm_counter(mm, MM_FILEPAGES) + get_mm_counter(mm, MM_SHMEMPAGES);
    /* mm->end_code 向上圆整,mm->start_code 向下圆整,以 PAGE_SIZE 为单位 */
    *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT;
    *data = mm->data_vm + mm->stack_vm;
    /* MM_FILEPAGES + MM_SHMEMPAGES + MM_ANONPAGES */
    *resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
    /* 返回值是总占用的虚拟内存 */
    return mm->total_vm;
}


3. 实验

(1) 通过这个文件看,主线程的和各个子线程的cat出来的值是完全一样的

P=593; cat /proc/$P/statm; for T in `ls /proc/$P/task/`; do cat /proc/$P/task/$T/statm; done;

(2) 累加所有进程的第二个成员

TDIR=/proc; let RSS=0; for P in `ls $TDIR | grep "^[0-9]"`; do if [ -f $TDIR/$P/statm ]; then TEP=`cat $TDIR/$P/statm | awk '{print ($2)}'`; RSS=$((RSS + TEP)); fi; done; RSS=$((RSS * 4)); echo RSS=$RSS"KB";

 

posted on 2024-08-26 21:53  Hello-World3  阅读(11)  评论(0编辑  收藏  举报

导航