数据缓存高速缓存

数据缓存高速缓存

1.作用

在操作系统中,对文件系统的一切存取操作内核都能够通过对磁盘块的读与写来实现;但是,磁盘操作相对于CPU的速度来说过慢,
会使系统的响应时间加长,吞吐率下降;内核通过保存一个在内存中的被称为数据缓存高速缓存(buffer cache)的数据结构缓冲
池来缓存磁盘块;缓冲池中含有最近被使用的磁盘块的数据,通过缓存磁盘块起到减小对磁盘的存取频率的作用

2.操作

buffer cache存在Unix内核中位于文件子系统与块设备驱动程序之间,作为块数据传输的桥梁。当内核需要读取或者写某个磁盘块时,
先从buffer cache中查找该磁盘块,如果该磁盘块存在于buffer cache中,则不需要读取磁盘块,如果不在buffer cache中,则从磁盘
中读取该磁盘块,缓存该磁盘块在buffer cache中,下次读取该块是不需要在读取磁盘


缓冲区的结构

1. 缓冲区的构成: 一个缓冲区由两部分构成—一个含有磁盘块数据的内存数组和一个用来标识该缓冲区的缓存头部
数据缓存高速缓存

2. 缓存头部(buffer header)

  • 作用: 缓存头部用来标识缓存区中的内容以及缓存区的状态
  • 内容:
    > - 设备号字段与块号字段:指明文件系统逻辑号与块号
    > - 状态字段: 是否上锁、是否延迟写、数据是否有效、是否正在把缓冲区写到磁盘或者往缓冲区读数据、等待该缓冲区有效的进程

3. 缓冲区的结构

  • 空闲链表: 空闲链表为双向循环链表,连接所有的空闲(即此刻没有正在被使用)的缓冲区
    free list

  • hash队列: hash队列使用逻辑设备号和块号来在常数时间内查找缓冲区
    hash queue


缓存区算法

1. getblk算法

getblk算法根据输入的设备逻辑号与块号来获取上锁的含有该磁盘块数据的缓冲区。
该算法先判断该特定的磁盘块的数据是否在缓冲池中,如果不在则分配一个空闲缓冲区。

  • 把一个缓冲区分配给磁盘块时可能出现的的五种情况

    • 该块在散列队列中,且该缓冲区空闲: 对该缓冲区上锁,并在空闲链表中除去该缓冲区
    • 该块在散列队列中,但是缓冲区为忙: 进程阻塞在该缓存区上,待占用该缓冲区的进程释放该缓冲区时该进程被唤醒,重新查找
    • 该块不在散列队列中,从空闲表头部分配一个缓冲区:块不在散列队列中,从空闲链表头部分配一个缓冲区,该缓存区没有被标记"延迟写",则上锁并从空闲链表中移除该缓冲区,重新填写缓冲区头部信息
    • 该块不在散列队列中,从空闲链表分配缓存区时缓冲区有“延迟写”的标记:当从空闲链表中取出的缓冲区有“延迟写”的标记时,内核使用异步写将该标记为“延迟写”的缓存区数据写入磁盘中,并查找空闲链表中的另一个缓冲区。待异步写完成时,内核将该缓冲区放入空闲链表头部。
    • 该块不在散列队列中,且空闲链表为空*: 使该进程睡眠,待任意一个缓冲区被释放可用时,唤醒该进程,该进程重新搜索需要的缓冲区

2. brelse算法

brelse算法用与释放缓冲区并对缓冲区解锁;该算法先唤醒等待任何一个缓冲区可用的进程,再唤醒等待该缓冲区可用的进程,并在对空闲链表进行操作时提高了处理机执行级别来防止多个进程同时对空闲链表进行操作破坏空闲链表的数据结构,如果该缓存区被标记为"旧",则该算法将该缓冲区放入空闲链表头部。

algorithm brelse
input: locked buffer
output: none
{
   wake up all procs: events, waitting for any buffer free;
   wake up all  process: events, waitting for this buffer to become free;
   raise processor execution level to block interrupts;
   if (buffer contents vaild and buffer not old)
       enqueue buffer at end of free list
   else
       enqueue buffer at beginning of free list
   lower processor excution level to allow interrupts;
   unlock(buffer);
}

读写磁盘块算法

1. 读磁盘块算法(bread)

读取磁盘块时,先用getblk算法在buffer cache中搜索该磁盘块,如果该磁盘块数据在buffer cache中,则立即返回该磁盘块即可;如果不在buffer cache中,则同步读取磁盘块数据,使用调用磁盘驱动程序,按排一个"读"请求,然后睡眠来等待I/O事件的发生。

algorithm bread
input: file system block number
output: buffer containning data
{
    get buffer for block(algorithm getblk);
    if (buffer data vaild)
        return buffer;
    initiate disk read;
    sleep(event disk read complete);
    return(buffer);
}

2. 读块与提前读 (breada算法)

考虑到局部性原理,使用提前读算法,在同步读取某个磁盘块时,同时异步读取该磁盘块的另一个磁盘块数据到缓冲区中以便在下次读取该缓冲区时不需要同步读写该磁盘块,可以直接在bufffer cache中获取该磁盘块。

algorithm breada /* block read and read ahead */
input: (1) file system block number for immerdiate read
(2) file system block number for asynchronous read
output: buffer containing data for immediata read
{
if (first block not in cache)
{
get buffer for first block (algorithm getblk);
if (buffer data not vaild)
initiate disk read;
}
if (second block not in cache)
{
get buffer for second block (algorithm getblk);
if (buffer data vaild)
release buffer (algorithm brelse);
else
initiate disk read;
}
if (first block was originally in cache)
{
read first block (algorithm bread);
return buffer;
}
sleep(event first buffer contain vaild data);
return buffer;
}

3. 写磁盘块算法(bwrite)

写磁盘算法接受一个缓冲区,然后将该缓冲区的数据写入到磁盘上,如果该缓冲区被标记为"延迟写",则对该缓冲区进行标记,使用brelse算法来释放该缓冲区,不用执行I/O操作;如果没有标记为"延迟写",则使用同步写即可;

algorithm: bwrite
input: buffer
output: none
{
    initiate disk write;
    if (I/O synchronous)
    {
        sleep(event I/O complete);
        release buffer (algorithm brelse);
    }
    else if (buffer marked for delayed write)
        mark buffer to put at head of free list;
}

你可能感兴趣的:(缓存)