Linux文件IO(五)IO内核

Linux内核实现I/O主要在三个内核子系统:虚拟文件系统(VFS),页缓存,和页回写。
虚拟文件系统(有时也叫做virtual file switch)是一种Linux内核的文件操作的抽象机制。它允许内核在无需了解文件系统类型的情况下,使用文件系统函数和操作文件系统数据。VFS实现这种抽象的方法是使用一种通用文件模型,它是所有Linux文件系统的基础。基于函数指针和各种面向对象方法,通用文件模型提供了一种Linux内核文件系统必须遵循的框架。它允许VFS对文件系统发起请求。框架提供了钩子来支持读,建立链接,同步以及其他功能。每种文件系统再使用合适的函数来处理相应操作。
页缓存是一种在内存中保存最近在磁盘文件系统上访问过的数据的方式。相对于现在的处理器速度而言,磁盘访问速度过慢。在内存中保存被请求数据,内核在接下来对相同数据的后续请求可以直接从内存中读取,尽量避免重复磁盘访问。页缓存利用了引用局部性(localityofreference)的一种方法------时间局部性(temporallocality),该方法使刚被访问资源很可能会在不久后再次被访问。由于避免了费时的磁盘访问,内存在第一次访问时缓存数据的开销因而得到补偿页缓存是内核寻找文件系统数据的第一目的地。只有缓存中找不到时内核才会调用存储子系统从磁盘中读取数据。,内核使用缓冲区来延迟写操作。当一个进程发起写请求,数据被拷贝进一个缓冲区,并将该该缓冲区标记为”脏”的,这意味着内存中的拷贝要比磁盘上的新。此时,写请求就可以返回了。如果对同一个数据块有新的写请求,缓冲区就更新为新数据。在该文件其他部分的写请求则开辟新的缓冲区。
页回写是将 那些”脏”缓冲区写入磁盘,将磁盘文件和内存数据同步。有两个条件会触发回写:
1,当空闲内存小于设定的阈值时,脏的缓冲区就会回写到磁盘上,被清理的缓冲区可能会被移除,来释放内存空间;
2,当一个脏的缓冲区寿命超过设定的阈值时,缓冲区被回写至磁盘。以此来避免数据的不确定性。

I/O调度器和I/O性能
磁盘寻址要理解I/O调度器的工作机制,需要先了解一些背景知识。硬盘基于用柱面(cylinders),磁头(heads),和扇区(section)几何寻址方式来获取数据,这种方式也被成为CHS寻址。每个硬盘都是由多个盘片组成,每个盘片包括一个磁盘、一个主轴和一个读写头。

I/O调度器实现两个基本操作:
1,合并(merging)操作是将两个或多个相邻的I/O请求的过程合并为一个。考虑两次请求,一次读取5号块,另一次读取6和7上的数据。这些请求被合并为一个对块5到7的操作。总的I/O吞吐量可能一样,但是I/O的次数减少了一半。
2,排序(sorting)是选取两个操作中相对更重要的一个,并按块号递增的顺序重新安排等待的I/O请求。比如说,I/O操作要求访问块52,109,和7,I/O调度这三个请求以7,52,109的顺序进行排序.如果一个请求现在要访问81,它将被插入到访问52和109的中间。I/O调度器然后按他们在队列中的顺序一次调度:7,然后52,然后81,最后109。

每次读请求必须返回最新的数据。因此,当请求的数据不在页缓存中时,读请求在数据从磁盘读出前一直会阻塞——这可能是一个相当漫长的操作。我们将这种性能损失称为读延迟(read latency)。一个典型的程序可能在短时期有几个I/O请求。因为每个请求都分别进行同步,稍后的请求将依赖于前面请求。当写操作需要在队列中插入多个块时,队列尾部的块读延迟会变得非常严重。这种现象就是著名的writes-starving-reads问题。
I/O 调度器使用一种机制避免”饿死”的发生。最简单的方法就是像2.4内核那样采用Linux电梯调度法。在该方法中,如果队列中有一定数量的旧的请求,则停止插入新的请求。这样整体上可以做到平等对待每个请求,但在读的时候,却增加了读延迟(read latency)。2.6内核丢弃了Linus电梯调度算法,转而使用了几种新的调度器算法。
1,Deadline I/O调度器,是为了解决2.4调度程序及传统的电梯调度算法的问题。Linus电梯算法维护了一个经过排序的I/O等待列表。队列首的I/O请求是下一个被调度的。DeadlineI/O调度器保留了这个队列,为了进一步改进了原来的调度器,增加了两个新的队列:读FIFO队列和写FIFO队列。FIFO 队列中的每个请求都设置一个过期时间。读 FIFO队列的过期时间设置为500毫秒,写队列则为5 秒。
2,Anticipatory I/O调度器,Deadline I/O调度器表现很好,但是并不完美。当面对众多独立的读请求时,问题依然会出现-每个读请求在前一个请求返回后才会执行,当应用程序得到数据,准备运行并提交了下一个读请求时, I/O 调度程序已经去处理其他的请求了。这样导致了每次搜索时都要进行不必要的寻道操作:查找数据,读数据,返回。
AnticipatoryI/O调度器在Deadline I/O调度器中增加了预测机制,当一个读操作被提交,anticipatory I/O 调度器在它的终止期限前调度它。不同于Deadline I/O 调度器的是, anticipatory I/O 调度器会等待6毫秒。如果应用程序在6 毫秒内对硬盘同一部分发出另一次读请求,读请求立刻被响应, anticipatory I/O 调度器继续等待。
3,CFQ I/O调度器,尽管在方法上有所区别,但Complete Fair Queuing(CFQ)I/O调度器和上述调度程序的目标是相同的。使用CFQ时,每个进程都有自己的队列,每个队列分配一个时间片。I/O调度程序使用轮转方式访问并处理队列中的请求,直到队列的时间片耗尽或所有的请求都被处理完。后一种情况,CFQ I/O调度器将会空转一段时间(默认10毫秒),等待当前队列中新的请求。如果预测成功,I/O调度器避免了查找操作。如果预测无效,调度程序转而处理下一个进程的队列。
4,Noop I/O调度器,NoopI/O调度程序是目前最简单的调度器。无论什么情况,它都不进行排序操作,只是简单的合并。它一般用在不需要对请求排队的特殊设备上。

调度器默认的I/O调度器可以在启动时可以通过内核参数iosched来指定。有效的选项有as,cfq,deadline,和noop。也可以在运行时针对每个块设备进行选择,可以通过修改/sys/block/device/queue/scheduler来完成。读这个文件可以知道当前的I/O调度器是什么,把上述有效选项写入这个文件可以更改I/O调度程序。例如,要设置设备hda的I/O调度程序为CFQ , 可以使用如下方式:
#echo cfq >/sys/block/hda/queue/scheduler

因为磁盘I/O相比系统其它部分很慢,同时I/O系统又是现代计算机很重要的一个部分,因此使I/O性能达到最优是非常重要的。减少I/O操作的次数(通过将很多小的操作聚集为一些大的操作),实现块对齐的I/O,或者使用用户空间缓冲,利用高级I/O的优点,如向量I/O,定位I/O和异步I/O,都是系统编程过程中需要经常考虑的重要步骤。为了使I/O请求能以有利于寻址操作的顺序提交,用户空间程序可以做不同的处理。它们可按照以下方式进行排序:
1,完整路径:在大部分文件系统采用的布局算法中,每个目录里的文件, 倾向于在磁盘上相邻分布。
2,inode编号:使用inode排序比路径排序更有效 ,通常情况下,inode的顺序意味着物理块的顺序。
3,文件的物理块:通过文件逻辑块获得物理块,然后再排序。。第一步,确定文件中块的数量。这可以通过stat()调用来完成。其次,对每个逻辑块,我们用ioctl()调用获得与它相关的物理块。

原文地址:http://blog.51cto.com/13376824/2060952

时间: 2024-07-30 10:08:44

Linux文件IO(五)IO内核的相关文章

聊聊 Linux 中的五种 IO 模型

本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451b5f14bf809aec77dd5df6cff&scene=21#wechat_redirect 上一篇<聊聊同步.异步.阻塞与非阻塞>已经通俗的讲解了,要理解同步.异步.阻塞与非阻塞重要的两个概念点了,没有看过的,建议先看这篇博文理解这两个概念点.在认知上,建立统一的模型.这样,大家在

[Z] linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

原文链接:http://blog.csdn.net/colzer/article/details/8169075 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据

linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性).那么我们的应用程序对文件的读写就通过对描述符的读写完成. linux将内存分为内核区,用户区.l

(转)linux网络编程之IO模型

原文:http://www.cnblogs.com/kunhu/p/3624000.html 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:  

Linux下5种IO模型的小结

概述 接触网络编程,我们时常会与各种与IO相关的概念打交道:同步(Synchronous).异步(ASynchronous).阻塞(blocking)和非阻塞(non-blocking).关于概念的区别在知乎上看到一位朋友(链接)打了一个比较形象的比喻: 你打电话问书店老板有没有<分布式系统>这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果).而异步通信机制,书店老板直接告诉你我查一下啊,查好了打

Linux 性能优化之 IO 子系统 系列 图

http://blog.sina.com.cn/s/articlelist_1029388674_11_1.html Linux 性能优化之 IO 子系统(一) 本文介绍了对 Linux IO 子系统性能进行优化时需要考虑的因素,以及一些 IO 性能检测工具. 本文的大部分内容来自 IBM Redbook - Linux Performance and Tuning Guidelines FileSystem VFS(Virtual FileSystem) 虚拟文件系统 文件系统是内核的功能,是

Day 40(07/21)五 IO模型

五 IO模型 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non-blocking IO是一个东西.这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(context)也不相同.所以,为了更好的回答这个问题,先限定一下本文的上下文.本文讨论的背景是Linux

Linux 环境下 网络IO模型

本文讨论的背景是Linux环境下的network IO. IO发生时涉及的对象和步骤: 对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel).当一个read操作发生时,它会等待内核经历两个阶段: 1  内核数据准备 (Waiting for the data to be ready) 2  内核把数据从内核空间,拷贝到用户空间中 (Copying the data from

Linux 性能监测:IO

磁盘通常是计算机最慢的子系统,也是最容易出现性能瓶颈的地方,因为磁盘离 CPU 距离最远而且 CPU 访问磁盘要涉及到机械操作,比如转轴.寻轨等.访问硬盘和访问内存之间的速度差别是以数量级来计算的,就像1天和1分钟的差别一样.要监测 IO 性能,有必要了解一下基本原理和 Linux 是如何处理硬盘和内存之间的 IO 的. 内存页 上一篇 Linux 性能监测:Memory 提到了内存和硬盘之间的 IO 是以页为单位来进行的,在 Linux 系统上1页的大小为 4K.可以用以下命令查看系统默认的页

黑马程序员------IO(五)

黑马程序员------IO(五) 1.1  操作对象(示例1)ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable. Serializable:用于给被序列化的类加入ID号,用于判断类和对象是否是同一个版本 类通过实现java.io.Serializable接口以启用序列化功能,Serializable只是一个标记接口. 1 示例1: 2 import java.io.*; 3 4 class ObjectStreamDemo 5