free 命令

free

\ total used free shared buffers cached
Mem 3908800 1149620 2759180 0 53744 866408
-/+ buffers/cache 229468 3679332
Swap 3145720 0 3145720

Line 1 : 指出了内存使用的情况,比如 总量、可用、已用、共享、buffer使用的内存、cache使用的内存(磁盘cache)
Line 2 : 指出了 buffer/Cache 已用与可用
Line 3 : 指出了交换区可用的内存,展示出了已用和可用交换区内存大小

Line 1
  1. 3908800 指出了该机器有多少物理内存(单位KB)
  2. 1149620 指出了系统已经使用了多少内存(这个大小包括 cache 与 buffer)
  3. 2759180 指出了还有多少内存可以使用(与代表一个新程序最多还能使用多少内存)
  4. 0 它指出了共享内存,这列如今没什么用了,未来free 命令可能废除这列
  5. 53744 指出了在Linux下的所有程序共使用了多少内存当作buffer
  6. 866408 指出了多少内存用来当做磁盘的cache

buffer 与 cache

  Buffer 是临时用来存数据的空间。当你尝试发送大量的数据往网络上的时候,如果你的网卡网速很低,没办法大量的发送数据,那么将会有大量的数据被滞留在buffer中以此来不断地慢慢地降低网速(减少访问硬件的频率)。所以它实际上是硬件设备的缓冲区。
  另一方面Cache是用来保存不断被使用到的数据的一个区域,它主要是为了提高访问数据的速度。所以它实际上就是操作系统的内核缓冲区,比如read系统调用时就是内核缓冲区中的数据读取到应用层。
  buffer与cache不通的点主要在于cache中的数据会被多次使用而buffer保存的数据只使用一次。这个就像我们平常调用read/write函数,这些磁盘上的数据就被加载到内存,那么操作系统会预读更多的数据到cache中,那么当我们下次调read/write函数顺序读取的时候不用再去磁盘读取了,这样大大的提高了访问数据的速度。而对于buffer来说,一般都是用来刷新到硬件上的数据,它被刷完之后就会被抛弃,所以只使用一次。

文件Cache作用

  buffer 与 cache 都属于文件cache。文件Cache的管理与内存管理系统和文件系统都息息相关。首先,Cache作为内存的一部分,需要参与内存的分配与回收,那么这个过程是由内存管理系统去负责的。其次,文件Cache的数据都来自于硬件,它需要与硬件进行读写交互,所以需要用文件系统使用文件Cache与硬件交互数据。所以,文件Cache可以看做是内存管理系统与文件系统之间的沟通桥梁,所以文件Cache管理也是操作系统一个重要组成部分。
在这里插入图片描述

文件Cache 相关结构

  从逻辑上讲文件Cache区分为PageCache 与 BufferCache,但是本质上BufferCache是属于PageCache的一种。每一个PageCache都包含了若干个BufferCache ,PageCache通过buffer_head指针去操作BufferCache。在操作系统中,VFS和VMM只与page_Cache交互,VMM负责 page_cache的分配与回收,同时在需要mmap时建立映射。VFS负责 应用层数据与 page_cache的交互。而buffer_cache只与具体的文件系统进行交互,具体的文件系统负责外设与BufferCache之间进行数据交互。

BufferCache 与文件与硬件关系

  File中是文件的逻辑地址,所以相邻的文件地址真正存到磁盘的数据并不一定相邻。
在这里插入图片描述
  page_cache 管理 buffer_cache
在这里插入图片描述

page_cache管理

  page_cache通过俩个数据结构管理。一个是radix_tree 一个是双向链表。Radix_tree 是属于inode节点来管理的,它主要负责根据文件偏移量来快速索引到page_cache。双向链表则是主要负责page_cache的回收,在内核中主要维护了active_list 与 inactive_list 俩个链表来实现物理内存的回收,这也就是Linux中的页面置换算法。
  下图是 radix tree的一个示意图,该 radix tree 的分叉为4(22),树高为4,用来快速定位8位文件内偏移。Linux(2.6.7) 内核中的分叉为 64(26),树高为 6(64位系统)或者 11(32位系统),用来快速定位 32 位或者 64 位偏移,radix tree 中的每一个叶子节点指向文件内相应偏移所对应的Cache项.
在这里插入图片描述

page_cache的预读与替换策略

  Linux内核的文件预读算法主要根据Cache是否命中来决策。当一次读请求的时候,Linux会读入所请求的页面并读入紧随其后的少数几个页面(不少于一个页面,通常是三个页面),这个时候的读取为同步读取。接下来的策略就看Cache是否命中

  1. 如果命中,系统把预读group扩大一倍,并让底层具体的文件系统继续读取其后的block块到page_cache中,这个时候读取称为异步读取
  2. 如果没命中,则表示文件并非顺序访问,此次读取页面不在之前预读的group中,系统继续采用同步读取,读取正确的数据到group中。

如下a显示读前结果,b显示未命中结果,C显示命中结果
在这里插入图片描述

页面置换伪代码
Mark_Accessed(b) {
 if b.state==(UNACTIVE && UNREFERENCE) 
       b.state = REFERENCE
else if b.state == (UNACTIVE && REFERENCE) {
          b.state = (ACTIVE && UNREFERENCE)
          Add X to tail of active_list
 } else if b.state == (ACTIVE && UNREFERENCE) 
          b.state = (ACTIVE && REFERENCE)
}
Reclaim()   {
  if active_list not empty and scan_num<MAX_SCAN1
      {
          X = head of active_list
          if (X.state & REFERENCE) == 0
              Add X to tail of inactive_list
          else 
          {
             X.state &=  ~REFERENCE Move X to tail of active_list
          }
          scan_num++
      }
      scan_num = 0
      if inactive_list not emptry and scan_num < MAX_SCAN2 
      {
            X = head of inactive_list 
            if (X.state & REFERENCE) == 0
                        return X
           else 
           {
                  X.state = ACTIVE | UNREFERENCE 
                  Move X to tail of active_list
            }
            scan_num++
        }
      return NULL
}
Access(b)
{
        if b is not in cache {
            if slot X free
               put b into X
             else {
               X=Reclaim()
                put b into X
              }
          Add X to tail of inactive_list
        }
         Mark_Accessed(X)
}

文件操作API与 page_cache关系

非mmap

  这类API基本上是用于 应用层数据 与 page_cache的交互,或者page_cache之间的互相交互
在这里插入图片描述

mmap

  第二种类型的API将page_cache项映射到用户空间,使得应用程序可以像使用内存指针一样访问文件,mmap 访问Cache的方式在内核中是采用请求页面机制实现的,其工作过程如下图所示。

  1. 应用程序调用mmap(图中1)
  2. 陷入到内核中后调用do_mmap_pgoff(图中2)
  3. 该函数从应用程序的地址空间中分配一段区域作为映射的内存地址,并使用一个VMA(vm_area_struct)结构代表该区域,之后就返回到应用程序(图中3)
  4. 当应用程序访问mmap所返回的地址指针时(图中4),由于虚实映射尚未建立,会触发缺页中断(图中5)。
  5. 系统会调用缺页中断处理函数(图中6),在缺页中断处理函数中,内核通过相应区域的VMA结构判断出该区域属于文件映射,于是调用具体文件系统的接口读入相应的Page Cache项(图中7、8、9),并填写相应的虚实映射表。
  6. 经过这些步骤之后,应用程序就可以正常访问相应的内存区域了。
    在这里插入图片描述

Line 2

  回头继续看Line2,used229468 表示应用程序真正使用到的内存大小。它的大小为 MemUsed - buffer - cached = 1149620 - 53744 - 866408 = 229468 。因为Linux 统计mem的时候包含了cache、buffer所以它的值显示出1149620而不是229468。但是如果即将有任何应用去想使用这些buffer/cache的空间,Linux将释放buffer/cache将其给应用使用。
  3679332 是用Memtotal - Used = 3908800 - 229468 得到的,它表示用户还能使用多少内存空间。

\ total used free shared buffers cached
Mem 3908800 1149620 2759180 0 53744 866408
-/+ buffers/cache 229468 3679332

Line3

  最后是swap区,它是由硬盘映射成虚拟内存,用来扩大虚拟内存容量,当访问swap区的内存时,发现其在硬盘上不在内存上会发生页面置换,把swap区的内容加载到内存,把内存的不用的页换回到硬盘上。

\ total used free shared buffers cached
Swap 3145720 0 3145720
选项
free -k   kb
free -m  mb
free -g   Gb
free --tera  -Tb
free --si -g   以1000为单位显示大小默认1024
free -t    显示 swap和内存的综合
free -s 1  以 num秒数为间隔输出结果
watch free 加上watch可以更好的动态使用free命令

猜你喜欢

转载自blog.csdn.net/sdoyuxuan/article/details/82750380