zoukankan      html  css  js  c++  java
  • 《Linux 性能及调优指南》1.4 硬盘I/O子系统

    翻译:飞哥 (http://hi.baidu.com/imlidapeng)

    版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明。

    原文名称:《Linux Performance and Tuning Guidelines》

    原文地址:http://www.redbooks.ibm.com/abstracts/redp4285.html

    -------------------------------------------------------------------------------------------

    1.4.1 I/O子系统架构
    1.4.2 缓存
    1.4.3 块层
    1.4.4 I/O设备驱动
    1.4.5 RAID及存储系统

    -------------------------------------------------------------------------------------------


    ​在处理器解码和执行指令前,先从扇区中读取数据并将数据置于处理器的缓存和寄存器中。执行结果会被写回硬盘。

    下面我们将简单地介绍一下Linux硬盘I/O子系统,来更好的认识这个可以对系统性能产生很大影响的组件。


    ​1.4.1 I/O子系统架构

    图1-18展示了I/O子系统架构的基本概念。


    图1-18 I/O子系统架构

    为了能快速的对I/O子系统运作有一个整体的认识,我们将举一个写数据到硬盘的例子。
    ​下面的步骤概述了当一个硬盘写操作执行时的基本操作。
    ​假设存储于硬盘片扇区上的数据已经被读取到分页缓存中。


    ​1.进程使用write()系统调用发出写文件的请求。

    2.内核更新映射此文件的分页缓存。

    3.pdflush内核线程将分页缓存清空至硬盘。

    4.文件系统层将多个块缓冲【block buffer】置于bio结构中(参见1.4.3,“块层”)并提交一个写请求给块设备层。

    5.块设备层从上一层收到请求,执行一个I/O elevator操作并发出进入I/O请求队列的请求。

    6.设备驱动如SCSI或其它设备的特定驱动来负责完成写操作。

    7.硬盘设备韧体负责执行硬件操作像确定磁头、旋转和传输数据至磁盘片上的扇区。


    ​1.4.2 缓存

    在过去的20年里,处理器性能的提升已超过计算机中其它元件如处理器缓存、总线、RAM、硬盘等。
    ​内存和硬盘较慢的访问速度限制了系统的整体性能,所以单单提高处理器速度并不能让系统性能提升。
    ​缓存机制通过将常用数据缓存至快速内存中来解决此问题。它减少了访问较慢内存的机会。
    ​目前计算机系统中几乎所有的I/O元件都是用了这项技术如硬盘驱动器缓存、硬盘控制器缓存、文件系统缓存、各种应用程序的缓存等等。


    ​内存层级【Memory Hierarchy】

    图1-19展示了内存层级的概念。
    ​CPU寄存器和硬盘在访问速度上有着很大的差距,CPU需要花费更多的时间等待从缓慢硬盘上获取数据,这显然降低了一个快速CPU所带了的好处。
    ​内存层级结构通过在CPU和硬盘间部署一级缓存、二级缓存、RAM和其他一些缓存可以减少这种速度上的失衡。
    ​它能减少处理器访问较慢内存和硬盘的机会。靠近处理器的内存拥有更快的访问速度但容量却较小。

    这种技术也可以利用局部性引用原则。快速内存中更高的缓存命中率就意味着更高的数据访问速度。


    图1-19 内存层级

    局部性引用【Locality of Reference】

    正如我们前面在“内存层级”中所述,取得更高的缓存命中率是性能提升的关键。
    ​为取得更高的缓存命中率,“局部性引用”技术被使用。这项技术是基于下面的原则:

    ▶ 最近使用过的数据非常有可能在近期被再次使用(时间局部性)

    ▶ 位于使用过数据相邻的数据非常有可能被使用(空间局部性)


    ​图1-20说明了这个原则。


    图1-20局部性引用


    ​这个原则被应用于Linux的许多元件中如分页缓存、文件对象缓存(i-node缓存、目录项缓存等)、预读缓冲以及更多。


    ​清空脏缓冲【Flushing a dirty buffer】

    当进程从硬盘中读取数据时,数据被复制到内存。
    ​此进程和其他进程都可以从缓存在内存中的副本取得相同数据。当有进程尝试变更数据,会先更改内存中数据。
    ​此时,硬盘中数据和内存中数据发生不一致,内存中数据被称为脏缓冲。
    ​赃缓冲会被尽快同步至硬盘,但如果系统突然崩溃内存中数据就会丢失。

    同步脏数据的进程叫做flush。

    ​在Linux2.6内核中,pdflush内核线程负责清空数据到硬盘。
    ​此操作会定期(kupdate)执行或者当内存中脏缓冲比例超过临界值(bdflush)时执行。
    ​此临界值配置在/proc/sys/vm/dirty_background_ratio文件中。
    ​更多信息参见4.5.1“设置内核交换和pdflush行为”。


    图1-21清空脏数据


    ​1.4.3 块层
    块层负责管理所有关于块设备操作的相关活动(参见图1-18)。
    ​块层中的关键数据结构就是bio,bio结构是位于文件系统层和块层之间的一个接口。

    当执行写操作时,文件系统层尝试向由块缓冲组成的分页缓存中写入。
    ​将连续的块组成一个bio结构,然后将bio传送至块层。(参见图1-18)

    块层获得bio请求并将其链接至I/O请求队列(I/O Request Queue)中。
    ​​这个链接操作叫做I/O调度器【原文中使用的单词为elevator】。

    ​​在Linux 2.6内核中,共有四种I/O调度器算法可以选择,他们是:

    块的大小【Block Sizes】

    块大小(读写硬盘数据的最小数量)能直接影响服务器的性能。
    ​一个指导性方案是,如果你的服务器处理非常多的小文件,较小的块大小会更有效率。
    ​如果你的服务器用于处理大文件,较大的块大小可以提升性能。
    ​已有的文件系统是不能更改块大小的,只有在重新格式化时才能修改当前块大小。


    ​I/O调度器

    Linux 2.6内核的I/O调度器使用了新模式,而Linux 2.4内核中采用的是一种简单、通用的I/O调度器,而在2.6内核中有四种调度器可供选择。
    ​因为Linux被用来执行各种各样的任务,对I/O设备和负载要求有显著的不同,一台笔记本电脑和一台有10000个用户的数据库对I/O的需求就有很大差别。

    ​​为满足这样的需求,Linux提供了四种I/O调度器。

    ▶ Anticipatory

    Anticipatory I/O 调度器是基于假设块设备只有一个物理寻址磁头(例如一个单SATA驱动)。
    ​Anticipatory 调度器使用了增加预测启发能力的Deadline机制(下面会详细介绍)。
    ​正像名字所暗示的,Anticipatory I/O Anticipatory会“猜测”I/O并尝试使用单一较大的数据流写入硬盘代替多个小的随机硬盘访问。
    ​这种预测启发能力会造成写入的延迟,但它可以提高一般用途系统如个人电脑的写入吞吐量。
    ​在2.6.18内核中Anticipatory 调度器被作为标准的I/O调度器,然而大多数企业发行版默认使用CFQ 调度器。


    ​▶ 完全公平队列(CFQ)

    CFQ elevator通过为每个进程都维护单独的I/O队列来实现QoS(服务质量)策略。
    ​CFQ调度器也适用于拥有许多互相竞争进程的多用户系统。它可以避免进程饿死并降低延迟。
    ​自从2.6.18内核,CFQ调度器已被作为默认的I/O调度器。


    ​依据系统设置和负载情况,CFQ调度器可以降低单一主应用程序的速度,例如使用其公平向导算法的大型数据库 。
    ​默认配置进程组确保公平,进程组与其它进程竞争。
    ​例如数据库所有写分页缓存(所有pdflush实例为一个群组)的操作被认为是一个应用程序与其它后台进程竞争。
    ​在这样的情况下它对于测试I/O调度器配置或Deadline调度器也是非常有用的。


    ​▶ Deadline

    Deadline是个使用最后期限算法的轮询调度器(Round Robin),它提供I/O子系统接近实时的操作。
    ​Deadline在维持满意的硬盘吞吐量的同时可以提供优秀的请求延迟。Deadline的算法能确保不会有进程被饿死。


    ​▶ NOOP

    NOOP代表不操作【No Operation】,名字就说明了其主要功能。
    ​NOOP简单且直接,它只实现一个简单的FIFO队列并不对任何数据排序。
    ​NOOP只是简单地合并数据请求,因此它增加非常低的处理器负载。
    ​NOOP假设块设备拥有自己的调度器算法如SCSI的TCQ或没有寻道的延迟的块设备如闪存卡。


    ​注释:在2.6.18内核中可以为每个硬盘子系统设定特定的I/O调度器,不需要在系统级上设定。


    ​1.4.4 I/O设备驱动

    Linux内核使用设备的驱动程序来控制设备。设备的驱动程序通常为独立的内核模组,它让操作系统中的每个设备都可以使用。
    ​当设备驱动被加载后,它就作为内核的一部分运行并完全控制设备。

    ​​这里我们将介绍一下SCSI设备驱动。

    SCSI

    小型计算机系统接口(SCSI)是一种最常用的I/O设备技术,特别是在企业服务器环境中。
    ​在Linux内核的实现中,SCSI设备由设备驱动模组控制。它们由下面几种模组构成。

    ▶ 上层驱动:sd_mod,sr_mod(SCSI-CDROM),st(SCSI Tape),sq(SCSI generic device)等。
    提供支持几种SCSI设备的功能如SCSI-CDROM,SCSI磁带等。

    ▶ 中间层驱动:scsi_mod
    实现SCSI协议和SCSI共有的功能。

    ▶ 底层驱动
    提供设备的底层访问。底层驱动为每个设备提供特定的硬件驱动。
    ​例如用于IBM ServeRAID控制器的ips、用于Qlogic HBA的qla2300、用于LSI Logic SCSI控制器的mptscsih等。

    ▶ 伪驱动:ide-scsi
    用于模拟IDE-SCSI。


    图1-22 SCSI驱动结构


    ​如果要设备实现特殊的功能,它需要在设备韧体和底层设备驱动中实现。
    ​支持什么功能取决于你使用什么设备和设备驱动的版本。设备自己也可以支持所希望的功能。
    ​通过设定设备驱动参数可以调整特定的功能。你可以调整/etc/modules.conf测试某些性能。关于使用方法和技巧请参见设备和驱动相关文档。


    ​1.4.5 RAID和存储系统

    就系统效能而言存储系统的选择配置与RAID类型也是重要因素。
    ​Linux支持软RAID,但此主题的详细内容已超出本文范畴,我将在4.6.1“安装Linux前硬件的选择”中介绍一些调优相关的内容。

  • 相关阅读:
    自我介绍
    学习进度第二周
    [BJDCTF2020]Easy MD5
    2020/2/13 bluecmsv1.6sp1代码审计
    [CISCN2019 总决赛 Day1 Web4]Laravel1
    [ByteCTF 2019]EZCMS
    2020/2/12 PHP编程学习
    [XNUCA2019Qualifier]EasyPHP
    [RoarCTF 2019]Online Proxy
    [GXYCTF2019]BabySQli
  • 原文地址:https://www.cnblogs.com/tcicy/p/10080076.html
Copyright © 2011-2022 走看看