📄 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.// // Interface:// * To get a buffer for a particular disk block, call bread.// * After changing buffer data, call bwrite to flush 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 three state flags internally:// * B_BUSY: the block has been returned from bread// and has not been passed back to brelse. // * B_VALID: the buffer data has been initialized// with the associated disk block contents.// * 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 "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 sector 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); loop: // Try for cached block. for(b = bufhead.next; b != &bufhead; b = b->next){ if((b->flags & (B_BUSY|B_VALID)) && b->dev == dev && b->sector == sector){ if(b->flags & B_BUSY){ sleep(buf, &buf_table_lock); goto loop; } b->flags |= B_BUSY; release(&buf_table_lock); return b; } } // Allocate fresh block. 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");}// Return a B_BUSY buf with the contents of the indicated disk sector.struct buf*bread(uint dev, uint sector){ struct buf *b; b = bget(dev, sector); if(!(b->flags & B_VALID)) ide_rw(b); return b;}// Write buf's contents to disk. Must be locked.voidbwrite(struct buf *b){ if((b->flags & B_BUSY) == 0) panic("bwrite"); b->flags |= B_DIRTY; ide_rw(b);}// 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -