procps源码学习笔记 free命令 001
开源代码路径:https://github.com/warmchang/procps.git
总结
free
命令打印内存参数的来源如下:
1.MEM部分:
MEMINFO_MEM_TOTAL
:直接来自设备meminfo节点,MemTotal: 2022668 kB。
MEMINFO_MEM_USED
:优先使用MemTotal-MemAvailable,
其次使用MemTotal-MemFree。
MEMINFO_MEM_FREE
:直接来自设备meminfo节点,MemFree: 186916 kB。
MEMINFO_MEM_SHARED
:直接来自设备meminfo节点,Shmem: 43336 kB。
MEMINFO_MEM_BUFFERS
:直接来自设备meminfo节点,Buffers: 52204 kB。
MEMINFO_MEM_CACHED_ALL
:(Cached: 692460 kB)+(SReclaimable: 77828 kB)。
MEMINFO_MEM_AVAILABLE
:直接来自设备meminfo节点,MemAvailable: 804656 kB。
MEMINFO_MEM_LOW_TOTAL
:直接来自设备meminfo节点,LowTotal,如果LowTotal值为0,就使用MemTotal代替。
MEMINFO_MEM_LOW_FREE
:直接来自设备meminfo节点,LowFree,如果LowFree值为0,就使用MemFree代替。
MEMINFO_MEM_LOW_USED
:LowTotal-LowFree。
MEMINFO_MEM_HIGH_TOTAL
:直接来自设备meminfo节点,HighTotal。
MEMINFO_MEM_HIGH_FREE
:直接来自设备meminfo节点,HighFree。
MEMINFO_MEM_HIGH_USED
:HighTotal-HighFree。
2.SWAP部分:
MEMINFO_SWAP_TOTAL
:直接来自设备meminfo节点,SwapTotal: 2744316 kB。
MEMINFO_SWAP_FREE
:直接来自设备meminfo节点,SwapFree: 1844116 kB。
MEMINFO_SWAP_USED
:SwapTotal-SwapFree。
3.TOTAL部分:
TOTAL
:MEMINFO_MEM_TOTAL+MEMINFO_SWAP_TOTAL。
USED
:MEMINFO_MEM_USED+MEMINFO_SWAP_USED。
FREE
:MEMINFO_MEM_FREE+MEMINFO_SWAP_FREE。
4.虚拟内存部分:
MEMINFO_MEM_COMMIT_LIMIT
:直接来自设备meminfo节点,CommitLimit: 3755648 kB。
MEMINFO_MEM_COMMITTED_AS
:直接来自设备meminfo节点,Committed_AS: 6016100 kB。
COMMIT_FREE
:CommitLimit-Committed_AS。
学习过程
gdb单步调试跟踪+SI源码阅读
- 查看main函数入参。
从下图可以看出当前free,入参个数是1个,入参内容是/home/xiao123/Downloads/code/procps-master/target_out/bin/free
。 - 单步跟踪,发现HAVE_PROGRAM_INVOCATION_NAME被定义。
查看该值与变量名意思一致,指的是改程序的绝对地址+程序名。
SI搜索未在代码中找到该宏定义的位置,看来是在编译时定义的。
- 单步跟踪setlocale
当setlocale用来转换当前字符格式为当前终端支持的格式。
如下函数也是设定国际化的。bindtextdomain是将国际化包名和具体的目录名绑定,textdomain通过包名来设置国际化文本域的。
setlocale (LC_ALL, "");bindtextdomain(PACKAGE, LOCALEDIR);textdomain(PACKAGE);atexit(close_stdout); // 退出时设置的处理函数。
- 参数检查,由于之前没有传递参数,所以这个代码段就不进入。
- 最后一个命令行参数判断。
- procps_meminfo_new函数阅读
由于ITEMTABLE_DEBUG没有定义,就直接跳过debug代码段,进行参数检查。
- meminfo_make_hash_failed函数
作用是创建hash table连接到meminfo_info.hashtab
中去,然后将/proc/meminfo中的参数一个一个保存到hash table中去。具体可以man 5 proc查看。
该函数完整执行结束,查看对应meminfo_info。当前参数有60,hsearch建议剩余25%。
- meminfo_read_failed函数
以上,通过将当前的meminfo数据拷贝到old中外,就判断当前meminfo_fd是否有效,不有效就打开一个文件句柄。
从打开的文件句柄中读取8k的内容,存到局部变量buf中。
循环读入meminfo内容,并保存在之前创建的hash_table中。
以上是内存显示调整的策略。 - 回到main函数中,现在就剩下一个主循环,显示内存的统计信息了。
- 单步跟踪print_head_col函数
这个函数意思是如果字符串小于9时,除过有效字符str外其余字符以空格填充。中间使用mbstowcs
计算当前的宽字符格式,以wcswidth
计算当前的宽字符占多少字节,以便后面方便填充空格
。 - scale_size(MEMINFO_GET函数单步调试。
上面表示打印信息以11字节右对齐方式打印。
MEMINFO_GET
这个宏定义其实是调用了procps_meminfo_get
函数,然后将此函数的结果返回。
单步procps_meminfo_get
函数发现,这个函数的逻辑大概为1.获取信息的时间间隔>=1s时,就会重新获取/proc/meminfo
节点信息;2.使用宏定义封装,来从hash_table中获取指定的信息。如下是从hash_table中获取的代码。
单步scale_size
函数,发现此函数有两种刻度方式表示,当启用了FREE_SI
的话,就会使用SI的方式去度量否则就会使用正常的计算机定义的刻度去度量。
如果没有定义FREE_HUMANREADABLE
,一般会按照期望的要求输入(比如按照K、M、G、T任意一个数量级输出)否则会按照K数量级输出。
如果有定义FREE_HUMANREADABLE
,则会按照人类可读的方式输出。 - 跳到主流程,如果指定了
FREE_WIDE
则按照下面方式输出。
- 如果指定了高低端内存则按照下面方式输出。
- 打印swap的内存情况。
- 如果指定了
FREE_TOTAL
部分则打印总的内存情况。
- 如果指定了
FREE_COMMITTED
,则会打印系统虚拟内存的使用情况。
上面分别打印了总的虚拟内存、已经使用的虚拟内存和剩余的虚拟内存。 - 如果指定了,则会按照要求持续打印指定的次数,未指定则会一直打印下去。
- 到此,这份源码就已经分析完了。