bio.c
来自「类unix x86平台的简单操作系统」· C语言 代码 · 共 152 行
C
152 行
// Buffer cache.//// The buffer cache is a linked list of buf structures// holding cached copies of disk block contents.// Each buf has two state bits B_BUSY and B_VALID.// If B_BUSY is set, it means that some code is currently// editing buf, so other code is not allowed to look at it.// To wait for a buffer that is B_BUSY, sleep on buf.// (See bget below.)// // If B_VALID is set, it means that the memory contents// have been initialized by reading them off the disk.// (Conversely, if B_VALID is not set, the memory contents// of buf must be initialized, often by calling bread,// before being used.)// // After making changes to a buf's memory, call bwrite to flush// the changes out to disk, to keep the disk and memory copies// in sync.//// When finished with a buffer, call brelse to release the buffer// (i.e., clear B_BUSY), so that others can access it.//// Bufs that are not B_BUSY are fair game for reuse for other// disk blocks. It is not allowed to use a buf after calling brelse.#include "types.h"#include "param.h"#include "x86.h"#include "mmu.h"#include "proc.h"#include "defs.h"#include "spinlock.h"#include "buf.h"struct buf buf[NBUF];struct spinlock buf_table_lock;// Linked list of all buffers, through prev/next.// bufhead->next is most recently used.// bufhead->tail is least recently used.struct buf bufhead;voidbinit(void){ struct buf *b; initlock(&buf_table_lock, "buf_table"); // Create linked list of buffers bufhead.prev = &bufhead; bufhead.next = &bufhead; for(b = buf; b < buf+NBUF; b++){ b->next = bufhead.next; b->prev = &bufhead; bufhead.next->prev = b; bufhead.next = b; }}// Look through buffer cache for block n on device dev.// If not found, allocate fresh block.// In either case, return locked buffer.static struct buf*bget(uint dev, uint sector){ struct buf *b; acquire(&buf_table_lock); for(;;){ for(b = bufhead.next; b != &bufhead; b = b->next) if((b->flags & (B_BUSY|B_VALID)) && b->dev == dev && b->sector == sector) break; if(b != &bufhead){ if(b->flags & B_BUSY){ sleep(buf, &buf_table_lock); } else { b->flags |= B_BUSY; // b->flags &= ~B_VALID; // Force reread from disk release(&buf_table_lock); return b; } } else { for(b = bufhead.prev; b != &bufhead; b = b->prev){ if((b->flags & B_BUSY) == 0){ b->flags = B_BUSY; b->dev = dev; b->sector = sector; release(&buf_table_lock); return b; } } panic("bget: no buffers"); } }}// Read buf's contents from disk.struct buf*bread(uint dev, uint sector){ struct buf *b; b = bget(dev, sector); if(b->flags & B_VALID) return b; ide_rw(dev & 0xff, sector, b->data, 1, 1); b->flags |= B_VALID; return b;}// Write buf's contents to disk.// Must be locked.voidbwrite(struct buf *b, uint sector){ if((b->flags & B_BUSY) == 0) panic("bwrite"); ide_rw(b->dev & 0xff, sector, b->data, 1, 0); b->flags |= B_VALID;}// Release the buffer buf.voidbrelse(struct buf *b){ if((b->flags & B_BUSY) == 0) panic("brelse"); acquire(&buf_table_lock); b->next->prev = b->prev; b->prev->next = b->next; b->next = bufhead.next; b->prev = &bufhead; bufhead.next->prev = b; bufhead.next = b; b->flags &= ~B_BUSY; wakeup(buf); release(&buf_table_lock);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?