前面咱们谈了的内容以下:node
这一节咱们将谈下Linux磁盘I/O子系统服务器
在进程解码和执行指令以前,要把数据从盘片的扇区中恢复到进程的缓存和寄存器中。程序执行结果又被写回到磁盘中。能够说,如今的服务器大部分都是I/O出现了瓶颈。网络
下图展现了基本的I/O子系统架构:数据结构
咱们以把数据写入磁盘为例。当执行向磁盘写入数据操做的时候,会发生以下的一系列基本操做。假设文件数据存在于磁盘扇区上,而且已经被读入到页缓存中。架构
以上就是程序把数据写到硬盘的大概过程。ide
在过去的20年里,处理器的性能提高要大于其它计算机组件(例如处理器缓存、总线、RAM 和磁盘等)。由于存储器和磁盘的速度限制了整个系统性能,因此系统的总体性能并无因 为处理器速度的提高而提高。可是,经过把经常使用数据放入到更快速度的内存中,以缓存机制 能够解决这个问题。它减小了访问比较慢的存储器的次数。现代计算机系统在几乎全部的I/O 组件中都使用了这项技术,例如硬盘驱动缓存(hard disk drive cache)、磁盘控制器缓存 (disk controller cache)和文件系统缓存(file system cache),各个应用都使用到了缓存。post
3.1 存储器层次
上展现了缓存等级的概念,因为CPU寄存器和磁盘之间的访问速度差别很大,CPU会花很 多时间等待磁盘中的数据,这致使CPU的高性能无用武之地。存储器层次结构经过L1 cache、L2 cache、RAM和其它在CPU和磁盘之间的缓存来消除这种影响。这减小了进程访 问较慢存储器和磁盘的机会。离处理器比较近的缓存拥有更高的CPU访问速度和较小的空间。
3.2 局部性引用(Locality of reference)
如上文所说,高缓存命中率是提高性能的关键。为了得到高缓存命中率,使用”局部性引用“的 技术。这个技术基于以下的原则:
Linux在不少组件中用到了这个原则,例如页缓存、文件对象缓存(i-node缓存、目录条 目缓存等等)、预读缓冲区等。以下图所示:
3.3 刷新脏缓冲区(Flushing a dirty buffer)
在进程从磁盘中读数据时,数据被复制到内存中。该进程和其它进程均可以在内存缓存中读 取一样的数据副本。当进程尝试改变数据,进程首先修改内存中的数据,这时候,磁盘和内 存中的数据就不一致了,内存中的数据就叫作脏缓冲(dirty buffer)。脏缓冲应该尽快同步到 磁盘上,不然,若是忽然崩溃,内存中的数据会丢失。
同步脏缓冲的进程叫作flush,在Linux内核2.6中,pdflush内核线程负责把数据写入到磁盘 上。数据会定时刷新(kupdate),或者当内存中的脏缓冲到了阀值的比例的时候 (bdflush)。这个阀值在/proc/sys/vm/dirty_background_ratio
文件中。
下图展现刷新脏缓冲区的过程:
块层处理全部和块设备相关的操做。块层中的关键数据结构是bio。bio结构是文件系统层和块 层之间的一个接口。
在执行写操做时,文件系统层尝试写入由块缓冲组成的页缓存。经过把相邻的块放在一块儿, 组成bio结构,而后把bio发送给块层。
块层处理bio请求,而且把请求连接到I/O请求队列中。这个连接操做叫作I/O elevator。在 Linux内核2.6中,有四种类型的I/O elevator算法。
4.1 块大小
驱动器上能够读出和写入的最小数据量会对服务器性能有直接影响。做为参考,若是服务器 要处理不少小文件,设置较小的块大小比较好。若是服务是须要处理大文件的,较大的块大 小可能会提升性能。不能改变运行中的文件系统的块大小,只有从新格式化才能修改当前的 块大小。
这里的块大小就是文件系统在格式化时指定的存储数据的block大小,如今的服务器由于硬盘容量巨大,因此通常设置block为4K大小。
4.2 I/O elevator
Linux2.6 内核使用了一种新的I/O elevator模型。Linux2.4提供的是一种通用目标的I/O elevator,2.6则提供了四个可用的elevator。由于Linux操做系统有各类普遍的用途,在不一样场 景下,I/O和负载都有很大的差别。一台Linux笔记本要知足的的I/O需求可能比一个10000用户 的数据库系统还多样。为了知足多样性,有四种可选的I/O elevator。
预期(Anticipatory) 预期 I/O elevator是基于假设一个块设备只有一个物理寻道指针(例如一块SATA盘)。预期 elevator使用期限(deadline)机制,而且加上了启发式的期限。正如名字所代表的,预期I/O elevator尝试往磁盘中写入一个大的流,而不是不少很是小的随机磁盘访问。启发式预期可能 会致使潜在的写I/O。它通常适用于的高吞吐的通用操做系统,例如pc。在内核2.6.18中, elevator是标准的I/O调度算法,可是,大多数企业Linux发行版仍是默认使用CFQ elevator。
彻底公平排队(CFQ,Complete Fair Queuing) 经过为每一个进程维护I/O队列,CFQ为进程实现QoS(服务质量,Quality of Service)策略。 CFQ elevator适用于拥有不少进程竞争的极多用户的系统。它努力的避免进程饿死,具备低 延时的特色。从内核2.6.18开始,增强版的CFQ elevator是默认的I/O调度器。 基于系统设置和负载模式,CFQ调度器可能拖慢一个主进程的运行,例如,一个使用公平算 法的大型数据库系统。根据默认配置,会彻底基于竞争处理进程组。一个单一的数据库,所 有的经过页缓存(全部的pdflush实例都在一个pgroup)的写都被CFQ认为是可以和其它不少 后台进程竞争的一个进程。在这个场景下,尝试I/O调度器子配置或deadline调度器可能更加 有用。
期限(Deadline) 期限elevator是使用dealine算法的循环elevator(轮询,round robin),提供接近实时行为的 I/O子系统。在维护不错吞吐量磁盘的时候,期限elevator具备优良的请求延迟。期限算法确保 不会发生进程饥饿的情况。
NOOP NOOP表示没有操做(No Operation),顾名思义。NOOP elevator很精简,它是简单的FIFO 队列,不作任何数据排序。NOOP把相邻的数据请求作简单的合并,对磁盘I/O来讲,它增长 了很是小的处理器开销。NOOP elevator假设块设备拥有本身的elevator算法,例如SCSI的 TCQ,或者没有寻道延迟,例如flash卡。
Linux内核使用设备驱动控制设备。设备驱动一般是一个独立的内核模块,为各个设备或者一 组设备提供Linux操做系统支持。一旦设备驱动被载入,就做为Linux内核的一部分运行,而且彻底控制设备。这里咱们会讨论SCSI设备驱动。
5.1 SISC
小型计算机系统接口(Small Computer System Interface,SCSI)是最经常使用的I/O设备和技 术,尤为在服务器环境。在Linux内核中,SCSI设备也受设备驱动模块控制。它由以下几个类 型的模块组成。
上层驱动程序(upper level drivers):sd_mod,sr_mode(SCSI-CDROM), st(SCSI Tape),sq(SCSI generic device)等等。它们提供了各类类型SCSI设备的 驱动功能,例如SCSI CD-ROM。
中间层驱动:scsi_mod 。实现SCSI协议和通用的SCSI功能。
低级别驱动程序,提供到各设备的低级别接入。底层驱动程序,基本上是特定于硬件设 备,而且提供给每一个设备。例如,ips是IBM ServerRAID控制器,ql2300专门为Qlogic HBA,mptscsih是LSI Logic SCSI的驱动器,等等。
伪驱动程序:ide-scsi。用做IDE-SCSI仿真。
下图展现了SCSI驱动的架构:
存储系统的选择和配置,以及RAID类型都是影响系统性能的重要因素。
磁盘阵列(Redundant Arrays of Independent Drives,RAID),有“独立磁盘构成的具备冗余能力的阵列”之意。通俗点说,磁盘阵列是由不少价格较便宜的磁盘,组合成一个容量巨大的磁盘组,利用个别磁盘提供数据所产生加成效果提高整个磁盘系统效能。利用这项技术,将数据切割成许多区段,分别存放在各个硬盘上。
有关RAID的详尽知识参考百度百科:磁盘阵列
在选择硬盘上,SSD > 高转速机械硬盘 > 低转速机械硬盘
谈完Linux的磁盘I/O子系统,下一节将会谈一下Linux的网络子系统