> 文章列表 > procps源码学习笔记 free命令 001

procps源码学习笔记 free命令 001

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源码阅读

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