os-xv6分析-文件系统-bio.c 代码分析

os-xv6分析-文件系统-bio.c 代码分析

// Buffer cache.
// 缓冲区缓存。
// The buffer cache is a linked list of buf structures holding
// cached copies of disk block contents.  Caching disk blocks
// in memory reduces the number of disk reads and also provides
// a synchronization point for disk blocks used by multiple processes.
//缓冲区缓存是保存磁盘块内容缓存副本的buf结构的链接列表。在内存中缓存//磁盘块可以减少磁盘读取的次数,并为多个进程使用的磁盘块提供一个同步点。
// Interface:
// * To get a buffer for a particular disk block, call bread.
// * After changing buffer data, call bwrite to write it to disk.
// * When done with the buffer, call brelse.
// * Do not use the buffer after calling brelse.
// * Only one process at a time can use a buffer,
//     so do not keep them longer than necessary.
//
// The implementation uses two state flags internally:
// * B_VALID: the buffer data has been read from the disk.
// * B_DIRTY: the buffer data has been modified
//     and needs to be written to disk.
// 导包
#include "types.h"
#include "defs.h"
#include "param.h"
#include "spinlock.h"
#include "sleeplock.h"
#include "fs.h"
#include "buf.h"
// 块缓存的管理数据结构
struct {
  struct spinlock lock; // 互斥锁
  struct buf buf[NBUF]; // 块缓冲区

  // Linked list of all buffers, through prev/next.
  // head.next is most recently used.
  struct buf head; //块缓存链表的头
} bcache;

//初始化函数,用于创建bcache互斥锁和将块缓存buf构成一个LRU双向链表
void
binit(void)  
{
  struct buf *b;

  initlock(&bcache.lock, "bcache"); //初始化锁

//PAGEBREAK!
  // Create linked list of buffers // 将全部buf构成双向链表
  bcache.head.prev = &bcache.head; 
  bcache.head.next = &bcache.head;
// 遍历buf数组,将每一个用头插法插入到链表中,head是头节点
// 之后都是通过访问链表,而不是数组buf来访问buffer
  for(b = bcache.buf; b < bcache.buf+NBUF; b++){
    b->next = bcache.head.next;
    b->prev = &bcache.head;
    initsleeplock(&b->lock, "buffer");
    bcache.head.next->prev = b;
    bcache.head.next = b;
  }
}

// Look through buffer cache for block on device dev.
// If not found, allocate a buffer.
// In either case, return locked buffer.
//bget应该是寻找磁盘上一个块对应的buffer,首先遍历链表,看该块是否已经
//缓存,如果是,那么直接返回。如果没有,那么从双端链表中找一个LRU的//buffer(empty slot),回收利用。
static struct buf*
bget(uint dev, uint blockno) //查找(含分配)指定盘块的块缓存
{
  struct buf *b;

  acquire(&bcache.lock); //获取锁

  // Is the block already cached?
// 从前往后扫描,因为一个已缓存的块,假设其是最近使用的
  for(b = bcache.head.next; b != &bcache.head; b = b->next){
    if(b->dev == dev && b->blockno == blockno){ //找到匹配的块缓存
      b->refcnt++; //
      release(&bcache.lock); //释放锁
      acquiresleep(&b->lock); //获得睡眠锁
      return b;
    }
  }

  // Not cached; recycle an unused buffer. //没有找到匹配的块缓存
  // Even if refcnt==0, B_DIRTY indicates a buffer is in use //B_Busy 和 B_DIRTY
  // because log.c has modified it but not yet committed it. //都不能直接回收利用
// 从后往前找,由于是找一个不适合的块,则其应该位是最近没有使用的
  for(b = bcache.head.prev; b != &bcache.head; b = b->prev){
    if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) { //找到适合块
      // 进行块分配
b->dev = dev;
      b->blockno = blockno;
      b->flags = 0;
      b->refcnt = 1;
      release(&bcache.lock); //释放锁
      acquiresleep(&b->lock); // 获得锁
      return b; // 返回这个缓存b
    }
  }
  panic("bget: no buffers"); // 否则输出无缓存
}

// Return a locked buf with the contents of the indicated block.

struct buf*
bread(uint dev, uint blockno) //读入一个盘块,返回它的块缓存
{
  struct buf *b;

  b = bget(dev, blockno); // 调用bget函数,找到或分配一个块缓存
  if((b->flags & B_VALID) == 0) { // 判断valid是否有数据
    iderw(b);  //通过IDE设备驱动程序iderw()读入
  }
  return b; //返回此缓存
}

// Write b's contents to disk.  Must be locked.
void
bwrite(struct buf *b) //写盘块
{
  if(!holdingsleep(&b->lock))  //判断是否正在使用
    panic("bwrite");
  b->flags |= B_DIRTY; 
  iderw(b); //通过IDE设备驱动程序iderw()写入
}

// Release a locked buffer.
// Move to the head of the MRU list.
void
brelse(struct buf *b)  //用完后释放,并挂到LRU链表头
{
  if(!holdingsleep(&b->lock))  //判读是否正在使用
    panic("brelse");

  releasesleep(&b->lock);  //释放睡眠锁

  acquire(&bcache.lock);  // 获得锁
  b->refcnt--;
 // 将b从原来的位置取下,放在链表开头
  if (b->refcnt == 0) {
    // no one is waiting for it.
    b->next->prev = b->prev;
    b->prev->next = b->next;
    b->next = bcache.head.next;
    b->prev = &bcache.head;
    bcache.head.next->prev = b;
    bcache.head.next = b;
  }
  
  release(&bcache.lock);  // 释放锁
}
//PAGEBREAK!
// Blank page.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值