操作系统I/O中的缓冲池

您所在的位置:网站首页 资源池包括什么操作系统网络 操作系统I/O中的缓冲池

操作系统I/O中的缓冲池

2024-07-15 07:22| 来源: 网络整理| 查看: 265

                                    操作系统I/O中的缓冲池

我们先来了解下操作系统缓冲技术的概念。为什么有缓冲这个东西呢?

缓冲,顾名思义就是起到一个调节的作用。我们知道cpu的处理速度是很快的,每秒钟百万条字节,而磁盘的I/O是

比较慢的,因为涉及到机械运动,性能差别很大。所以要有一个缓冲区用来缓和他们之间性能上的差异。磁盘I/O到

缓冲区中,然后缓冲区数据满了或者足够了之后通过总线放在cpu的高速缓冲区中,然后交给cpu处理,cpu处理完了

之后,回写到高速缓冲中。然后通过总线把数据放在缓冲区中。然后再回写到硬盘中。整个过程有两个甚至更多的缓

冲,为了就是解决性能上的差距。我们这里主要介绍下在磁盘I/O的缓冲技术中的缓冲池。

我们先来简单介绍除了缓冲池之外的其他缓冲技术。

1、单缓冲区:单个缓冲区是指要写到磁盘中的数据先放在缓冲区中,然后再把缓冲区的数据写到磁盘中。或者把磁盘

中的数据写在缓冲区中,然后由处理机取走。这种缓冲区由于要保证数据的正确性,而且缓冲区属于临界资源,需要进

行同步处理。只能有一个进程对数据进行写入或者读取。

2、双缓冲区:双缓冲区是指有两个缓冲区,当数据要写入磁盘的时候,首先写入第一缓冲区(a),第一缓冲区写满之后再

向第二个缓冲区(b)写入。当写入磁盘的时候,先把第一缓冲区(a)的数据写入到磁盘中。然后把第二个缓冲区(b)当作第一

个缓冲区(a)。再进行写入的时候写第二个缓冲区(a)。读操作类似。这样设计之后就能防止因缓冲区区域小导致数据写入

或者读取的不完整情况。提高并行性和设备的利用度。

3、循环缓冲区:

循环缓冲区是对单缓冲区的改良,这种缓冲区适合于读写速率差不多的情况,可以通过循环缓冲区来进行控制,这种机制

也可以提高设备的利用率。但是读写速率差距较大的时候,又不适合这种方式,这时候又可以引入多个缓冲区来适应速率

差别大的问题。

缓冲池技术:

缓冲池,说到底也是缓冲区,只不过这种缓冲区较其他缓冲区来说能更好的实现cpu并行和设备的利用率。

缓冲池里主要包括如下方面。用于对数据进行读写的公共区域:

1、 emq空缓冲队列:用于取出空缓冲区来进行读写等操作。

2、 inq输入队列:用来记录输入设备输入的数据,以便用户程序读取。

3、outq输出队列:用来记录用户程序输出到设备(显示屏或是文件等)的数据,以便用户程序读取。

先来分析下这个图的含义:

我们的缓冲区主要是有inq,outq,enq三个缓冲队列。其他四种hin,sout,sin,hout工作缓冲区是在这三种缓冲队列

上申请和取出缓冲区,用于数据的读取和存储。操作完成之后再把缓冲区放回到原来的队列。所以这四种缓冲区是抽象

出来的缓冲区,实际上还是在这三种缓冲队列上进行操作。下面我们来分析下四种操作对应是怎么实现的。

这四种工作缓冲区是在对应的队列中申请空间,所以我们有对对应的缓冲队列的读写两种操作。

Get_buf(封装Take_buf):从缓冲队列取出一个缓冲区的过程:

Void Get_buf(type) { Wait(RS(type)); //type是指缓冲队列的类型,RS是用来线程同步信号量,初始值是缓冲区的大小。 Wait(MS(type)); //MS是用来互斥的信号量,保证缓冲队列的同一缓冲区只能被一个线程操作。 B(number)=Take_buf(type); //number是指缓冲队列对应的位置,这里是得到缓冲队列的缓冲区。得到之后可以用来读写数据, Signal(MS(type)); //发送互斥信号,对缓冲队列中的空间操作完成。 }

Put_buf(封装Add_buf):从缓冲区插入对应缓冲队列的过程:

Void Put_buf(type,work_buf) { Wait(MS(type)); //MS是用来互斥的信号量,保证缓冲队列的同一缓冲区只能被一个线程操作。 Add_buf(type,work_buf); //type是指缓冲队列的类型,work_buf代表工作缓冲区的类型。 Signal(MS(type)); //发送互斥信号,对缓冲队列中的空间操作完成。 Signal(RS(type)); //给对应类型的缓冲区发信号,代表返回缓冲队列的空间 }

上面对应的四种操作就可以通过调用这两个函数,给出不同参数实现对应的功能。

1、收容输入:把设备输入的数据放在缓冲区中。

①首先从空缓队列取出一个缓冲区当作hin工作缓冲区,hin=Get_buf(emq)。把数据装入到hin中

②把得到的hin缓冲区放在inq缓冲队列。inq=Put_buf(inq,hin)。供给用户程序利用

2、提取输入:把缓冲区的数据交给用户程序处理。

①把inq缓冲队列中的数据提取到sin工作缓冲区中,sin=Get_buf(inq)。供给用户提取数据。

②提取完数据之后,把sin的工作缓冲区放回到emq空缓冲队列中。emq=Put_buf(emq,sin)。

3:收容输出:把用户程序处理完的数据放在缓冲区中。

①先用工作缓冲区hout向空缓冲队列emq申请缓冲区,得到用户处理的数据,hout=Get_buf(emq)。

②hout的数据读取完毕之后,放在outq缓冲区中。Put_buf(outq,hout)供给外设读取。

4:提取输出:

①先把要输出到设备的缓冲区中的数据放在sout工作缓冲区中。sout=Get_buf(outq)。

②提取完sout的数据之后,把sout缓冲区放到空缓冲队列而emq中。emq=Put_buf(emq,sout)

有了缓冲池支撑缓冲,能够大大提高设备和cpu的利用率。这时候可以允许多个线程来处理数据。A线程送完了数据之

后,直接执行其他部分。B线程过来的时候带走应用程序处理的A线程的数据。放在对应的位置。多个设备也可同时对

缓冲区的不同位置进行读写,互不干扰。效率大大提高。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3