CLion:2019.3.6
源码操作平台:Macbook Pro 10.12.6
源码项目:linux源码
一、背景
通过上一节,我们知道了top中的RES是从/proc/pid/statm文件中读取出来的,详细的可以看这篇博客《linux的top命令源码解析:RES指标》,这次我们要弄清楚/proc/pid/statm文件中resident值是怎么计算出来的。
二、克隆linux源码
2.1 linux源码
github上,linux的源码地址是:https://github.com/torvalds/linux。
linux源码有2.42G多,直接在github上克隆的话,速度才20-400kbits,速度相当的慢,所以可以从国内的码云上进行clone,速度能达到10Mbits,
码云上有linux的mirrors,地址是:https://gitee.com/mirrors/linux?_from=gitee_search,
由于linux的太大,如果直接执行clone的话会导致失败,如下所示:
Cloning into 'linux'...
remote: Counting objects: 20248, done.
remote: Compressing objects: 100% (10204/10204), done.
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
在stackoverflow上找到一个解决办法:error: RPC failed; curl transfer closed with outstanding read data remaining
首先执行git clone git@gitee.com:mirrors/linux.git --depth 1进行浅度clone:
192:gitee bingsanlang$ git clone git@gitee.com:mirrors/linux.git --depth 1
Cloning into 'linux'...
remote: Enumerating objects: 74374, done.
remote: Counting objects: 100% (74374/74374), done.
remote: Compressing objects: 100% (69764/69764), done.
remote: Total 74374 (delta 6338), reused 21640 (delta 3816), pack-reused 0
Receiving objects: 100% (74374/74374), 195.69 MiB | 5.79 MiB/s, done.
Resolving deltas: 100% (6338/6338), done.
Updating files: 100% (70001/70001), done.
warning: the following paths have collided (e.g. case-sensitive paths
on a case-insensitive filesystem) and only one from the same
colliding group is in the working tree:
'include/uapi/linux/netfilter/xt_CONNMARK.h'
.....省略.......
'tools/memory-model/litmus-tests/Z6.0+pooncelock+pooncelock+pombonce.litmus'
进入linux目录,执行fetch 将剩余代码clone下来:
192:gitee bingsanlang$ cd linux/
192:linux bingsanlang$ git fetch --unshallow
remote: Enumerating objects: 7588438, done.
remote: Counting objects: 100% (7588435/7588435), done.
remote: Compressing objects: 100% (1215473/1215473), done.
remote: Total 7530352 (delta 6369843), reused 7426929 (delta 6266881), pack-reused 0
Receiving objects: 100% (7530352/7530352), 2.42 GiB | 9.78 MiB/s, done.
Resolving deltas: 100% (6369843/6369843), completed with 51779 local objects.
remote: Enumerating objects: 659, done.
remote: Counting objects: 100% (659/659), done.
remote: Compressing objects: 100% (659/659), done.
remote: Total 659 (delta 0), reused 659 (delta 0), pack-reused 0
Receiving objects: 100% (659/659), 280.11 KiB | 612.00 KiB/s, done.
From gitee.com:mirrors/linux
* [new tag] v2.6.12 -> v2.6.12
.....省略.......
* [new tag] v5.9-rc1 -> v5.9-rc1
下载完成后,当前目录下主要有如下源码文件:
192:linux bingsanlang$ ls
COPYING Kconfig README crypto init mm security virt
CREDITS LICENSES arch drivers ipc net sound
Documentation MAINTAINERS block fs kernel samples tools
Kbuild Makefile certs include lib scripts usr
2.2 linux源码导入到Clion
参考《Clion 导入Makefile格式的C语言源程序:procps项目》将linux源码导入到CLion中,导入后如下结构:
2.3 /proc/pid/statm的resident数据源码分析
/proc/pid/statm 中的数据,是经过内核函数 task_statm 读取而后由 procfs 写入的。
具体源码如下:
文件:linux/fs/proc/task_mmu.c
其中的片段如下:
unsigned long task_statm(struct mm_struct *mm,
unsigned long *shared, unsigned long *text,
unsigned long *data, unsigned long *resident)
{
*shared = get_mm_counter(mm, MM_FILEPAGES) +
get_mm_counter(mm, MM_SHMEMPAGES);
*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
>> PAGE_SHIFT;
*data = mm->data_vm + mm->stack_vm;
*resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
return mm->total_vm;
}
从代码中可以看到,resident的大小 = 共享内存+MM_ANONPAGES大小,关于MM_ANONPAGES后面后讲述,简单介绍下get_mm_count函数:
文件:《