当前位置: 首页> 文旅> 美景 > 济南今日头条新闻_dw网页制作教程自我介绍代码_怎样建立自己的网站平台_重庆网站seo公司

济南今日头条新闻_dw网页制作教程自我介绍代码_怎样建立自己的网站平台_重庆网站seo公司

时间:2025/7/8 23:30:47来源:https://blog.csdn.net/suitaox26456/article/details/142535464 浏览次数:0次
济南今日头条新闻_dw网页制作教程自我介绍代码_怎样建立自己的网站平台_重庆网站seo公司

阅读材料

  • 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()函数

该函数首先检查是否持有睡眠锁,然后通过virtio_disk_rw函数写入虚拟磁盘中

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

bpin()函数

增加该buffer块的引用计数

void bpin(struct buf *b)
{acquire(&bcache.lock);b->refcnt++;release(&bcache.lock);
}

bunpin()函数

减少该buffer块的引用计数 

void bunpin(struct buf *b)
{acquire(&bcache.lock);b->refcnt--;release(&bcache.lock);
}

参考资料

The xv6 Kernel-28 Disk Buffer Cache_哔哩哔哩_bilibili

关键字:济南今日头条新闻_dw网页制作教程自我介绍代码_怎样建立自己的网站平台_重庆网站seo公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: