其他分享
首页 > 其他分享> > 第十二章学习笔记

第十二章学习笔记

作者:互联网

第12章学习笔记

一、概述

本章讨论了块设备IO和缓冲区管理;解释了块设备I/O的原理和I/O缓冲的优点;论述了Unix的缓冲区管理算法,并指出了其不足之处;还利用信号量设计了新的缓冲区管理算法,以提高IO缓冲区的缓存效率和性能;表明了简单的PV算法易于实现,缓存效果好,不存在死锁和饥饿问题;还提出了一个比较Unix缓冲区管理算法和PV算法性能的编程方案。

二、块设备I/O缓冲区

文件系统使用一系列IO缓冲区作为块设备的缓存内存。当进程试图读取(dev,blk)标识的磁盘块时,它首先在缓冲区缓存中搜索分配给磁盘块的缓冲区。如果该缓冲区存在并且包含有效数据,那么它只需从缓冲区中读取数据,而无须再次从磁盘中读取数据块。如果该缓冲区不存在,它会为磁盘块分配一个缓冲区,将数据从磁盘读入缓冲区,然后从缓冲区读取数据。当某个块被读入时,该缓冲区将被保存在缓冲区缓存中,以供任意进程对同一个块的下一次读/写请求使用。同样,当进程写入磁盘块时,它首先会获取一个分配给该块的缓冲区。然后,它将数据写入缓冲区,将缓冲区标记为脏,以延迟写人,并将其释放到缓冲区缓存中。由于脏缓冲区包含有效的数据,因此可以使用它来满足对同一块的后续读/写请求,而不会引起实际磁盘L/O。脏缓冲区只有在被重新分配到不同的块时才会写入磁盘。

三、Unix I/O缓冲区管理算法

Unix缓冲区区管理子系统

(1)I/O缓冲区:内核中的一系列NBUF缓冲区用作缓冲区缓存。每一个缓冲区用结构体标识。

(2)设备表:每个块设备用一个设备表结构表示。

(3)缓冲区初始化:当系统启动时,所有I/O缓冲区都在空闲列表中,所有设备列表和I/O队列均为空。

(4)缓冲区列表:当缓冲区分配给(dev,blk)时,它会被插入设备表的dev_list中。如果缓冲区当前正在使用,则会将其标记为USY并从空闲列表中删除。繁忙缓冲区也可能回在设备表的I/O队列中。

(5)Unix getblk/brelse算法

Unix算法的具体说明

(1)数据一致性:为了确保数据一致性,getblk一定不能给同一个( dev, blk)分配多个缓冲区。这可以通过让进程从休眠状态唤醒后再次执行“重试循环”来实现。读者可以验证分配的每个缓冲区都是唯一的。其次,脏缓冲区在重新分配之前被写出来,这保证了数据的一致性。
(2)缓存效果:缓存效果可通过以下方法实现。释放的缓冲区保留在设备列表中,以便可能重用。标记为延迟写入的缓冲区不会立即产生IO,并且可以重用。缓冲区会被释放到空闲列表的末尾,但分配是从空闲列表的前面开始的。这是基于LRU(最近最少使用)原则,它有助于延长所分配缓冲区的使用期,从而提高它们的缓存效果。
(3)临界区:设备中断处理程序可操作缓冲区列表,例如从设备表的I/O队列中删除bp,更改其状态并调用brelse(bp)。所以,在getblk和 brelse中,设备中断在这些临界区中会被屏蔽。这些都是隐含的,但没有在算法中表现出来。

Unix算法的缺点

虽然Unix算法非常简单和简洁,但它也有以下缺点。
(1)效率低下;该算法依赖于重试循环。例如,释放缓冲区可能会唤醒两组进程:需要释放的缓冲区的进程,以及只需要空闲缓冲区的进程。由于只有一个进程可以获取释放的缓冲区,所以,其他所有被唤醒的进程必须重新进入休眠状态。从休眠状态唤醒后,每个被唤醒的进程必须从头开始重新执行算法,因为所需的缓冲区可能已经存在。这会导致过多的进程切换。
(2)缓存效果不可预知:在Unix算法中,每个释放的缓冲区都可被获取。如果缓冲区由需要空闲缓冲区的进程获取,那么将会重新分配缓冲区,即使有些进程仍然需要当前的缓冲区。
(3)可能会出现饥饿:Unix算法基于“自由经济”原则,即每个进程都有尝试的机会,但不能保证成功。因此,可能会出现进程饥饿。
(4)该算法使用只适用于单处理器系统的休眠/唤醒操作。

四、PV算法

empty[s2] = m;
full[s2] = 0;
 
while(1)//写进程
{
for(i = 0; i< s2; i++)
{
P(empty[i]);
}
P(mutex);
消息放入缓冲区;
V(mutex);
for(i = 0; i< s2; i++)
{
V(full[i]);
}
}
 
 
while(1)//读进程
{
P(full[i]);
P(mutex);
读取缓冲区;
V(mutex);
V(empty[i]);
}

接下来,我们要证明PV算法是正确的,并且满足要求。

(1)缓冲区唯一性:在 getblk()中,如果有空闲缓冲区,则进程不会在(1)处等待,而是会搜索 dev list。如果所需的缓冲区已经存在,则进程不会重新创建同一个缓冲区。如果所需的缓冲区不存在。则进程会使用个空闲缓冲区来创建所需的缓冲区。而这个空闲缓冲区保证是存在的。如果没有空闲缓冲区,则需要同一个缓冲区的几个进程可能在(1)处阻塞。当在(10)处释放出一个空闲缓冲区时,它仅释放一个进程来创建所需的缓冲区。一旦创建了缓冲区,它就会存在于dev list中,这将防止其他进程再次创建同一个缓冲区。因此,分配的每个缓冲区都是唯一的。

(2)无重试循环:进程重新执行while(1)循环的唯一位置是在(6)处,但这不是重试,因为进程正在不断地执行。

(3)无不必要唤醒:在 getblk(中,进程可以在(1)处等待空闲缓冲区也可以在(4)处等待所需的缓冲区。在任意一种情况下,在有缓冲区之前,都不会唤醒进程重新运行。此外,当在(9)处有一个脏缓冲区即将被释放并且在(1)处有多个进程等待空闲缓冲区时,该缓冲区不会被释放而是直接被写入。这样可以避免不必要的进程唤醒。

(4)缓存效果:在 Unix算法中,每个释放的缓冲区都可被获取。而在新的算法中,始终保留含等待程序的缓冲区以供重用。只有缓冲区不含等待程序时,才会被释放为空闲。这样可以提高缓冲区的缓存效果。

(5)无死锁和饥饿:在 getblk()中,信号量锁定顺序始终是单向的,即 P(free),然后是P(bp),但决不会反过来,因此不会发生死锁。如果没有空闲缓冲区,所有请求进程都将在(1)处阻塞。这意味着,虽然有进程在等待空闲缓冲区,但所有正在使用的缓冲区都不能接纳任何新用户。这保证了繁忙缓冲区最终将被释放为空闲缓冲区。因此,不会发生空闲缓冲区饥饿的情况。

五、I/O缓冲区管理算法比较

项目分为以下几个结构:

openeuler实践

perror ( )函数

perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。

源代码:

问题与解决

1、为什么要有输入输出缓冲区?
答:
有输入输出缓冲区用以暂时存放读写期间的文件数据而在内存区预留的一定空间。即利用主存的存储空间来暂存从磁盘中输入输出的信息。目的是缓和CPU 与 I/O 设备间速度不匹配的矛盾。减少对 CPU 的中断频率,放宽对 CPU 中断响应时间的限制。提高 CPU和 I/O 设备之间的并行性。

2、日常较为常见的计算机缓冲区有哪几种类型?
答:
日常较为常见的缓冲区,根据缓冲的应用层次不同,分别可以分为以下几种类型:主板与CPU的缓存,这两者是基于计算机硬件层次的缓冲区,能够有效地提高计算机的数据处理能力;操作系统与网络协议层的缓冲区,这则是在系统软件层的分类,为了提高访问速度,网站门户常常会基于缓冲原理使用一些组件,以实现信息的快速交互;在应用程序这一次层,缓冲区又可分为应用程序、数据库系统的缓冲区等等,一般来说,开发较为完善的大型软件会自己配备内存管理程序,在运行软件运行时自动进行对缓冲区的管理。

标签:缓存,第十二章,笔记,学习,进程,算法,缓冲区,CPU,空闲
来源: https://www.cnblogs.com/kevin-hw/p/15584506.html