当前位置: 首页 > news >正文

Xv6文件系统(一):缓存层

阅读材料

  • Xv6代码:buf.h、bio.c
  • Xv6教材第8章 8.1-8.3节

缓存层作用

缓存层,也就是教材中的Buffer cache layer,是Xv6整个文件系统中最低一层,该层直接读、写磁盘的数据。该层在整个文件系统的作用如下:

  1. 同步对磁盘块的访问,以确保内存中只有一个块的副本,并且一次只有一个内核线程使用该副本
  2. 为了减少从磁盘读块,缓存常用的块

Buffer cache数据结构

缓存层用一个循环双向链表实现的LRU来管理struct buf,总共有NBUF(定义在param.h)个struct buf

其中,头节点是dummy节点,并不真实存储数据

struct
{struct spinlock lock;struct buf buf[NBUF];struct buf head;
} bcache;

struct buf的结构如下

struct buf
{int valid; // has data been read from disk?int disk;  // does disk "own" buf?uint dev;uint blockno;struct sleeplock lock;uint refcnt;struct buf *prev; // LRU cache liststruct buf *next;uchar data[BSIZE];
};

缓存层接口

binit()函数

该函数是Xv6内核初始化时,文件系统模块第一个调用的函数,是整个文件系统的根基

该函数首先初始化bcache的自选锁,然后遍历所有buf,初始化每个buf的睡眠锁,并插入到双向链表中

void binit(void)
{struct buf *b;initlock(&bcache.lock, "bcache");// Create linked list of buffersbcache.head.prev = &bcache.head;bcache.head.next = &bcache.head;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;}
}

bread()函数

该函数返回指定块号的副本,通过调用bget函数得到该块。如果该块还未被缓存到内存,则调用virtio_disk_rw函数从磁盘中读取。virtio_disk_rw函数(定义在virtio_disk.c)是Xv6虚拟磁盘驱动提供的唯一接口,用来对虚拟磁盘进行读/写操作

struct buf* bread(uint dev, uint blockno)
{struct buf* b;b = bget(dev, blockno);if (!b->valid){virtio_disk_rw(b, 0);b->valid = 1;}return b;
}

bget函数用于遍历整个链表,寻找合适的缓存块

注意:这里其实依赖blocknorefcnt被隐式初始化为0的事实,不然会有bug

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 the least recently used (LRU) unused buffer.for (b = bcache.head.prev; b != &bcache.head; b = b->prev){if (b->refcnt == 0){b->dev = dev;b->blockno = blockno;b->valid = 0;b->refcnt = 1;release(&bcache.lock);acquiresleep(&b->lock);return b;}}panic("bget: no buffers");
}

 bwrite()函数

void bwrite(struct buf *b)
{if (!holdingsleep(&b->lock))panic("bwrite");virtio_disk_rw(b, 1);
}

 

 

 


http://www.mrgr.cn/news/36380.html

相关文章:

  • 图像预处理 图像去噪之常见的去噪方法
  • 当okhttp网络库遇到不规范的http状态码
  • Python_异常机制
  • java 框架组件
  • 【RabbitMQ】幂等性、顺序性
  • 拉格朗日乘子法的详细说明和示例
  • 【最简单最直观的排序 —— 插入排序算法】
  • MariaDB 和 MySQL 全面对比:选择数据库需要考虑这几点
  • windows 驱动实例分析系列-COM驱动的I/O处理
  • 【2024/9/25更新】最新版植物大战僵尸V2.5.1发布啦
  • [前端]DOM+CSS+HTML实现水波进度效果
  • 【WRF数据介绍第二期】气象驱动场数据介绍及下载
  • 系统分析师13:软件工程
  • HashMap哈希表练习
  • Springboot Mybatis XML配置文件
  • 毕业设计选题:基于ssm+vue+uniapp的自助购药小程序
  • 快手一面:给定一棵二叉树,要求将其转换为其镜像?
  • python库 | lxml库
  • 使用AI进行需求分析的案例研究
  • 进制数知识(2)—— 浮点数在内存中的存储 和 易混淆的二进制知识总结