free 命令 buffers and cached 解释

N多人总是询问,当在linux在输入free时内存总数怎么加起来不一样啊,下面我来解释一下free命令的输出。

我们运行free命令时都会看到如下的信息:
#free
total used free shared buffers cached
Mem: 1025236 1002324 22912 0 26900 228140
-/+ buffers/cache: 747284 277952
Swap: 1044216 53912 990304
今天我主要讲讲第一行的buffers和cached的含义。
free命令显示的 buffers 上面是 26900 和 cached 上面是 228140,这些数字是从 /proc/meminfo中获取的。
#cat /proc/meminfo | grep Buffers
Buffers: 26912 kB
#cat /proc/meminfo | grep Cached
Cached: 228180 kB
会有些不同是因为你没有在同时运行命令,命令之间有时间间隔,你再试试这个命令:
#cat /proc/meminfo | grep Buffers;free
Buffers: 27624 kB
total used free shared buffers cached
Mem: 1025236 987924 37312 0 27624 197972
应该一样了吧。

那么具体buffers和cached代表什么意思呐,我们看一下kernel code.
首先我们看buffers
proc中的meminfo初始化是在 proc_misc_init ,其中会 初始化 meminfo_read_proc 函数,当我们cat /proc/meminfo此函数会被调用。
meminfo_read_proc 会打印Buffers信息 是通过 i.bufferram的值打印的,具体 i 是什么结构很简单你看看代码就明白了。
我们主要看看i.bufferram是怎么统计的。
meminfo_read_proc -> si_meminfo(&i) 进行统计
void si_meminfo(struct sysinfo *val)
{
...
val->bufferram = nr_blockdev_pages(); //统计Buffers
...
}
long nr_blockdev_pages(void)
{
struct list_head *p;
long ret = ;
spin_lock(&bdev_lock);
list_for_each(p, &all_bdevs) { //查看所有块设备
struct block_device *bdev;
bdev = list_entry(p, struct block_device, bd_list); //指向一个块设备
ret += bdev->bd_inode->i_mapping->nrpages; //统计页数
}
spin_unlock(&bdev_lock);
return ret;
}
函数意思是查找所有的块设备然后通过块设备的inode的i_mapping统计页数,那么nrpages是怎么增加的,谁又会引用inode和i_mapping,我们继续向下看。
int add_to_page_cache(struct page *page, struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
{
int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM); if (error == ) {
write_lock_irq(&mapping->tree_lock);
error = radix_tree_insert(&mapping->page_tree, offset, page);
if (!error) {
page_cache_get(page);
SetPageLocked(page);
page->mapping = mapping;
page->index = offset;
mapping->nrpages++; //更新mapping的nrpages字段
__inc_zone_page_state(page, NR_FILE_PAGES);
}
write_unlock_irq(&mapping->tree_lock);
radix_tree_preload_end();
}
return error;
}
void __remove_from_page_cache(struct page *page)
{
struct address_space *mapping = page->mapping; radix_tree_delete(&mapping->page_tree, page->index);
page->mapping = NULL;
mapping->nrpages--;
__dec_zone_page_state(page, NR_FILE_PAGES);
}
我搜索kernel发现最终更新mapping->nrpages字段的函数就是add_to_page_cache和__femove_frome_page_cache函数,
那么他们使用的mapping是块设备的吗还是文件的呐,文件的inode中自带了mapping如果是文件的mapping传递进来了,那么更新的就不是块设备的信息,Buffer信息也不会反应。
如果传递的是块设备的mapping那么相应的统计信息会从Buffer中反应出来。
那么我们下面就可以看看kernel中哪些地方是把块设备的mapping传递进来了。 sys_read ->vfs_read 其中会调用 file->f_op->read(file, buf, count, pos);
那么如果文件是一个目录就会调用相关目录的操作函数read,我们以ext3举例:
sys_getdents (读目录系统调用) -> vfs_readdir -> file->f_op->readdir(file, buf, filler); 调用相关文件系统的读目录函数
那么ext3就下面
const struct file_operations ext3_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = ext3_readdir, // 读目录函数
.ioctl = ext3_ioctl, /* BKL held */
.fsync = ext3_sync_file, /* BKL held */
#ifdef CONFIG_EXT3_INDEX
.release = ext3_release_dir,
#endif
};
ext3_readdir 函数会调用
ext3_get_blocks_handle,page_cache_readahead等函数
调用page_cache_readahead 时明显传递的是 sb->s_bdev->bd_inode->i_mapping,都会更新块设备的mapping->nrpages字段,
就是说当进行读目录时可能会增加Buffers的值,相应的当对目录进行操作时,像在目录中建立文件,重命名等动作都会涉及到mapping->nrpage字段。
还有就是当读取文件的间接块时也会更新mapping->nrpage字段,具体看看ext3_get_blocks_handle函数你就会明白了。
然后我们看cached
meminfo_read_proc中有
cached = global_page_state(NR_FILE_PAGES) - total_swapcache_pages - i.bufferram; //NR_FILE_PAGES的页面 - 所有交换缓存页和我们上面讲的buffers页。
那么global_page_state(NR_FILE_PAGES)是什么,我们下面进行解释。
static inline unsigned long global_page_state(enum zone_stat_item item)
{
long x = atomic_long_read(&vm_stat[item]);
#ifdef CONFIG_SMP
if (x < )
x = ;
#endif
return x;
}
vm_stat是一个枚举数组,下面的结构是枚举值。
enum zone_stat_item {
NR_ANON_PAGES, /* Mapped anonymous pages */
NR_FILE_MAPPED, /* pagecache pages mapped into pagetables. only modified from process context */
NR_FILE_PAGES,
NR_SLAB, /* Pages used by slab allocator */
NR_PAGETABLE, /* used for pagetables */
NR_FILE_DIRTY,
NR_WRITEBACK,
NR_UNSTABLE_NFS, /* NFS unstable pages */
NR_BOUNCE,
#ifdef CONFIG_NUMA
NUMA_HIT, /* allocated in intended node */
NUMA_MISS, /* allocated in non intended node */
NUMA_FOREIGN, /* was intended here, hit elsewhere */
NUMA_INTERLEAVE_HIT, /* interleaver preferred this zone */
NUMA_LOCAL, /* allocation from local node */
NUMA_OTHER, /* allocation from other node */
#endif
NR_VM_ZONE_STAT_ITEMS
};
看看上面两个函数
add_to_page_cache 有 __inc_zone_page_state(page, NR_FILE_PAGES);
_remove_from_page_cache 有 __dec_zone_page_state(page, NR_FILE_PAGES);
__add_to_swap_cache 也有 __inc_zone_page_state(page, NR_FILE_PAGES);
__delete_from_swap_cache 进行减少操作。
就是说所有调用 add_to_page_cache的函数都会进行统计,包括目录操作,文件的数据读取,再加上swap的就是NR_FILE_PAGES所有进行统计的信息。
这样会不会有重叠呐,不会看上面 cached 的算法 cached = global_page_state(NR_FILE_PAGES) - total_swapcache_pages - i.bufferram;
把重叠部分读减去了。

free 命令解释的更多相关文章

  1. 理解docker容器和镜像(layer,ufs)和docker命令解释

    博客好文1:http://blog.csdn.net/x931100537/article/details/49633107(理解docker容器和镜像,理解简单,从原理入手,什么是layer,什么是 ...

  2. 【转】nagios 命令解释

    nagios 命令解释 check_ssh                 界面拼装参数格式如下共3个元素:                         命令!端口!连接超时时间          ...

  3. nginx配置文件结构,语法,配置命令解释

    摘要: nginx的配置文件类似于一门优雅的编程语言,弄懂了它的规范就可以自定义配置文件了,这个很重要~ 1,结构分析 nginx配置文件中主要包括六块:main,events,http,server ...

  4. RYU改动监听port Mininet在custom自建拓扑和连接到指定控制器命令解释

    1.RYU控制器改动监听port 在ryu/ryu/ofproto以下的ofproto_common.py watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc ...

  5. linux 的sed命令解释 sed ':t;N;s/\n/,/;b t' 将换行符换成逗号

    linux 的sed命令解释 sed ':t;N;s/\n/,/;b t' 将换行符换成逗号 实现的功能是吧换行符换成逗号了,自己试验过. 求解释,:t N b t 都是什么意思??? :t 定义la ...

  6. UEFI Shell --常用命令解释

    UEFI Shell解释 UEFI Shell 是一个提供用户和UEFI系统之间的接口,进入UEFI Shell可以对计算机系统进行配置 命令解释: 单独的help就可以输出所有指令,不做特殊说明,内 ...

  7. Rational Rose的安装及使用教程(包括菜单命令解释、操作向导说明、快捷命令说明)

    一.安装教程 我安装时用的是镜像文件,所以安装前需要辅助软件来处理镜像文件.我用到的是UltraISO.UltraISO中文名叫软碟通 是一款功能强大而又方便实用的光盘映像文件的制作/编辑/转换工具, ...

  8. Linux常用性能检测命令解释

    1.uptime [root@smgsim02 ~]# uptime 15:08:15 up 98 days, 4:19, 2 users, load average: 0.07, 0.29, 0.1 ...

  9. ubuntu常用命令解释

    1.seq 用于产生一个整数到另一个整数之间所有的整数,如:seq 3 5 输出:3 4 5 注:如果参数为一个整数,则输出1至这个数之间的所有整数 2.tee [-a] file 从标准输入设备读取 ...

随机推荐

  1. IOS开发之NSPredicate谓词的用法

    编程的人员不管是上过大学还是从培训机构出来的或做后台的.前端的都应该SQL语句有所了解,我们知道,在SQL语句当中 where 条件表达式可以对二维关系表的数据做条件筛选.微软的C# .net中也实现 ...

  2. C bit 操作

    C 位 操作 一.C bit 操作(C语言 二进制位 操作) 1.Setting a bit Use the bitwise OR operator (|) to set a bit. number ...

  3. CLR has been unable to transition from COM context for 60 seconds

    Original link: http://blog.wpfwonderland.com/2007/08/16/clr-has-been-unable-to-transition-from-com-c ...

  4. POJ 2127 Greatest Common Increasing Subsequence -- 动态规划

    题目地址:http://poj.org/problem?id=2127 Description You are given two sequences of integer numbers. Writ ...

  5. OpenJudge/Poj 1915 Knight Moves

    1.链接地址: http://bailian.openjudge.cn/practice/1915 http://poj.org/problem?id=1915 2.题目: 总Time Limit: ...

  6. linux中 ECShop的文件不能写

    解决办法: 1.开放权限 使用命令:chmod -R 777 文件路径 2.关闭SELinux 使用命令:setenforce 0

  7. WIN7中oracle10g的安装注意事项

    1.本次安装数据库版本为10.2.0.1,操作系统版本为windows7 32位 2.注意在"setup.exe"中以右键属性后,设置以兼容模式及以管理员身份运行该程序:在%安装文 ...

  8. Python3 网络编程

    虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Microsoft都有各自的 ...

  9. 转 修改oracle用户密码永不过期

      1.查看用户的proifle是哪个,一般是default: sql>SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的 ...

  10. 用 BPL 封装数据连接

    BPL 代码: uDM.pas unit uDM; interface uses SysUtils, Classes, uIntf, DB, ABSMain; type TDM = class(TDa ...