【Linux】/proc/meminfo 解析
为了获取linux 当前的内存状态信息,可以直接使用Linux 提供的系统调用 sysinfo, 但是 sysinfo 获取的信息比较少,只有以下部分内容,其中totalram/ freeram/ sharedram/ bufferram 是一类,需要注意的是这里还缺usedram,
usedram 无法仅仅根据sysinfo 结构体的信息计算出来。
usedram = total - free -buff/cache 其中buff/cache = bufferram + cached + sreclaimable (可回收的slab大小),为了获取完整的mem 信息,可以直接读取/proc/meminfo ,这里会存在一个疑问,/proc/meminfo 是file system,那这个文件结点的更新频率足够快吗,每次读取是否最新的信息?
struct sysinfo {
__kernel_long_t uptime; /* Seconds since boot */
__kernel_ulong_t loads[3]; /* 1, 5, and 15 minute load averages */
__kernel_ulong_t totalram; /* Total usable main memory size */
__kernel_ulong_t freeram; /* Available memory size */
__kernel_ulong_t sharedram; /* Amount of shared memory */
__kernel_ulong_t bufferram; /* Memory used by buffers */
__kernel_ulong_t totalswap; /* Total swap space size */
__kernel_ulong_t freeswap; /* swap space still available */
__u16 procs; /* Number of current processes */
__u16 pad; /* Explicit padding for m68k */
__kernel_ulong_t totalhigh; /* Total high memory size */
__kernel_ulong_t freehigh; /* Available high memory size */
__u32 mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(__kernel_ulong_t)-sizeof(__u32)]; /* Padding: libc5 uses this.. */
};
file system 的解释 : it is not stored on any media (not even in RAM), so there is nothing to update.
The purpose of the proc file system is to allow userspace programs to obtain or set kernel data using the simple and familiar file system semantics (
open
,close
,read
,write
,lseek
),even though the data that is read or written doesn't reside on any media. This design decision was deemed better (e.g. human readable and easily scriptable) for getting and setting data whose format could not be specified in advance than implementing something such as ASN1 encoded OIDs,
which also would have worked fine. The data that you see when you read from the proc filesystem is generated on-the-fly when you do a read from the begining of a file.
That is, doing the read causes the data to be generated by a kernel callback function that is specific to the file you are reading. Doing an
lseek
to the begining of the file and reading again causes another call to the callback that generates the data again. Similarly, when you write to a writable file in the proc filesystem, a callback function is called that parses the input and sets kernel variables. The input data in it's raw form isn't stored.
这段话的意思就是,linux file system 并不是真的文件信息存储在磁盘上,每次读取/proc/meminfo 其实会触发一次kenel callback function ,然后实时生成这个结点的内容,也就是每次读取节点,其实获取的就是当前瞬时最新的数据结果。
接下来一起看看 /proc/meminfo 包含了哪些信息:
MemTotal: 所有内存(RAM)大小,减去预留空间和内核的大小。
MemFree: 完全没有用到的物理内存,lowFree+highFree。
MemAvailable: MemFree只是尚未分配的内存,并不是所有可用的内存。有些已经分配掉的内存是可以回收再分配的。比如cache/buffer、slab都有一部分是可以回收的,这部分可回收的内存加上MemFree才是系统可用的内存,即MemAvailable(不精确)。
Buffers: 块设备所占用的缓存页。块设备(block device)所占用的特殊file-backed pages,包括:直接读写块设备,以及文件系统元数据(metadata)比如superblock使用的缓存页。
Cached: 表示普通文件数据所占用的缓存页。用户进程的内存页分为两种:file-backed pages(与文件对应的内存页),和anonymous pages(匿名页),比如进程的代码、映射的文件都是file-backed,而进程的堆、栈都是不与文件相对应的、就属于匿名页。file-backed pages在内存不足的时候可以直接写回对应的硬盘文件里,称为page-out,不需要用到交换区(swap);而anonymous pages在内存不足时就只能写到硬盘上的交换区(swap)里,称为swap-out。
SwapCached: swap cache中包含的是被确定要swapping换页,但是尚未写入物理交换区的匿名内存页。那些匿名内存页,比如用户进程malloc申请的内存页是没有关联任何文件的,如果发生swapping换页,这类内存会被写入到交换区。
LRU:LRU是一种内存页回收算法,Least Recently Used,最近最少使用。LRU认为,在最近时间段内被访问的数据在以后被再次访问的概率,要高于最近一直没被访问的页面。于是近期未被访问到的页面就成为了页面回收的第一选择。Linux kernel会记录每个页面的近期访问次数,然后设计了两种LRU list: active list 和 inactive list, 刚访问过的页面放进active list,长时间未访问过的页面放进inactive list,回收内存页时,直接找inactive list即可。另外,内核线程kswapd会周期性地把active list中符合条件的页面移到inactive list中。
Active: active包含active anon和active file。
Inactive: inactive包含inactive anon和inactive file。
Active(anon): anonymous pages(匿名页),用户进程的内存页分为两种:与文件关联的内存页(比如程序文件,数据文件对应的内存页)和与内存无关的内存页(比如进程的堆栈,用malloc申请的内存),前者称为file pages或mapped pages,后者称为匿名页。
Inactive(anon): 见上。
Active(file): 见上。
Inactive(file): 见上。
SwapTotal: 可用的swap空间的总的大小(swap分区在物理内存不够的情况下,把硬盘空间的一部分释放出来,以供当前程序使用)。
SwapFree: 当前剩余的swap的大小。
Dirty: 需要写入磁盘的内存页的大小。
Writeback: 正在被写回的内存区的大小。
AnonPages: 未映射页的内存的大小。Anonymous pages(匿名页)数量 + AnonHugePages(透明大页)数量。
Mapped: 设备和文件等映射的大小。正被用户进程关联的file-backed pages。
Slab: 内核数据结构slab的大小。slab是linux内核的一种内存分配器。
SReclaimable: 可回收的slab的大小。
SUnreclaim: 不可回收的slab的大小。
PageTables: 管理内存页页面的大小。Page Table的用途是翻译虚拟地址和物理地址,它是会动态变化的,要从MemTotal中消耗内存。
NFS_Unstable: 不稳定页表的大小。发给NFS server但尚未写入硬盘的缓存页。
VmallocTotal: Vmalloc内存区的大小.可分配的虚拟内存总计.
VmallocUsed: 已用Vmalloc内存区的大小
VmallocChunk: vmalloc区可用的连续最大快的大小.通过vmalloc可分配的虚拟地址连续的最大内存