Date

原文Linux System and Performance Monitoring,作者Darren Hoch。

6.0 I/O监控相关

磁盘IO子系统是Linux系统中最慢的一部分。这主要是因为磁盘距离CPU较远以及磁盘工作的时候需要机械操作(磁盘转动及机械臂运动)。如果访问磁盘像访问内存一样只需要花费分钟和秒级别的时间,这就是7天和7分钟的差异。因此,Linux内核尽量减少磁盘读写量是及其必要的。下面几段描述了内核从磁盘读数据到内存和写回的几种方式。

6.1 读写数据——内存页

Linux内核是按页来读写磁盘的。一般Linux系统上默认的页大小是4KB,系统读写磁盘块的时候是以4KB为单位进行的。你可以通过time命令verbose模式的Page Size来查看你系统上的页大小。

image

6.2 大小缺页

正如大部分Unix系统一样,Linux使用的是虚拟地址,然后将虚拟地址映射到物理内存空间。映射的操作是用时建立的,即当一个进程启动时,内核只会将那些使用到的虚拟地址映射到实存中。当一个应用启动的时候,内核会依次查找CPU缓存和物理内存,如果都没有找到所需的数据,内核会触发一个大缺页(major page fault, MPF)中断。一个MPF中断会要求磁盘子系统从磁盘检索所需的页并将它们缓存到内存中。

一旦内存页(磁盘数据)被映射到了缓存中,内核会首先尝试使用这些数据,这就是小缺页(minor page fault, MnPF)。通过缓存和重用内存页而不是将这些页写回到磁盘上,小缺页帮助内核节约了很多时间。

在下面的例子中,time命令展示了一个程序启动的时候会有多少大小缺页产生。程序第一次启动的时候,会产生很多大缺页:

image

第二次evolution启动的时候,内核并不会产生大缺页了,因为应用(应用本身及应用所需数据)已经被缓存在内存中了:

image

译注:由此可见,大小缺页的区别在于是否需要从磁盘读取数据。

6.3 文件缓冲缓存

内核利用文件缓冲缓存可以将大缺页转换成小缺页。如果一个系统连续产生IO操作,文件缓冲缓存就会持续增长,直到可用内存很低时系统需要释放一些内存页给其他用户使用。结果就是很多系统管理员看到可用的内存很少而担心,但实际情况是系统充分利用了缓存而已。

下面是一个/proc/meminfo文件的内容:

# cat /proc/meminfo  
MemTotal: 2075672 kB  
MemFree: 52528 kB  
Buffers: 24596 kB  
Cached: 1766844 kB

这个系统一共有2GB的物理内存(MemTotal),现在有52MB的内存“可用”(MemFree),24MB的内存分配给了磁盘写操作(Buffers),还有17GB的内存缓存了磁盘文件(Cached)。

内核正是使用缓存和MnPF小缺页机制来避免所有数据都从磁盘获取(大缺页)。我们可以通过上面的统计数据看出系统是否在健康的状态。

6.4 内存页的类型

Linux内核中主要有三种内存页类型(非空闲页),如下:

  • Read Pages——这些页是通过磁盘读到内存的只读页,其备份(源数据)在磁盘。这些页存驻留在缓冲缓存中,一般是静态文件,二进制文件和库文件这类不变的数据。需要这些数据的时候,内核会把这些数据加载并缓存在内存。当空闲内存较少时,内核会“窃取”这些页将它们放到空闲列表中,这也会造成下次需要该数据时会触发一个大缺页。
  • Dirty Pages——这些页的数据在驻留内存期间已经被修改。在特定的时刻,这些页会被pdflush进程同步到磁盘。如果出现内存短缺,为了获得更多可用内存,kswapd会把这些页写到磁盘。
  • Anonymous Pages——这些页上的数据是属于某个进程的,但是它们并没有文件或者磁盘作为备份,因此它们不能被同步到磁盘。当出现内存短缺的时候,kswapd会临时把这些页写到交换设备直到空闲内存增多时再切换到内存。

6.5 数据页同步到磁盘

应用本身可以通过调用fsync()或sync()立即将脏页同步到磁盘。这两个系统调用会直接发送一个请求给IO调度器。如果应用不调用这两个系统调用来主动要求同步数据到磁盘,pdflush进程也会在一定的时间间隔之后将这些页写到磁盘。