MIT6.S081 Lab8 Locks

这篇博客详细介绍了操作系统中内存管理器(MemmoryAllocator)和缓冲区缓存(BufferCache)的实现原理。通过修改kalloc.c、kinit、kfree和kalloc等函数来实现内存分配器,利用自由列表进行内存管理。同时,缓冲区缓存的结构和bget、brelse、bpin、bunpin等操作展示了如何维护一个最近最少使用(LRU)缓存策略,确保高效的数据读取。
摘要由CSDN通过智能技术生成

国庆没啥事干,现在还剩3个半lab,快要做完啦,希望能有始有终,人活着真难,太难了。。。

Memmory其实就是用freelist实现的,而缓冲区Cache其实也是用freelist实现的,不过缓冲在disk的上一层,因为disk读取很慢,缓冲的定义在buf.h

struct buf {
  int valid;   // has data been read from disk? 缓存是否有数据可读,新分配的缓存,valid为0,
  int disk;    // does disk "own" buf?
  uint dev;
  uint blockno; //缓冲对应的磁盘块号
  struct sleeplock lock;
  uint refcnt; //有多少线程引用了这个缓冲,我猜的
  struct buf *prev; // LRU cache list
  struct buf *next;
  uchar data[BSIZE];
};

Memmory Allocator

1.修改kalloc.c

struct {
  struct spinlock lock;
  struct run *freelist;
} kmem[NCPU];

2. 修改kinit

void
kinit()
{
  push_off();
  int id = cpuid();
  initlock(&kmem[id].lock, "kmem");
  pop_off();
  freerange(end, (void*)PHYSTOP);
}

3. 修改kfree

void
kfree(void *pa)
{
  struct run *r;

  if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)
    panic("kfree");

  // Fill with junk to catch dangling refs.
  memset(pa, 1, PGSIZE);

  r = (struct run*)pa;

  push_off();
  int id = cpuid();
  pop_off();
  acquire(&kmem[id].lock);
  r->next = kmem[id].freelist;
  kmem[id].freelist = r;
  release(&kmem[id].lock);
}

4. 修改kalloc

void *
kalloc(void)
{
  struct run *r;

  push_off();
  int id = cpuid();
  pop_off();
  acquire(&kmem[id].lock);
  r = kmem[id].freelist;
  if(r)
    kmem[id].freelist = r->next;
  release(&kmem[id].lock);

  if(!r)
  {
    for(int i = 0; i < NCPU; i++)
    {
      acquire(&kmem[i].lock);
      if(kmem[i].freelist) {
        r = kmem[i].freelist;
        kmem[i].freelist = r->next;
      }
      release(&kmem[i].lock);
      if(r) break;
    }
  }

  if(r)
    memset((char*)r, 5, PGSIZE); // fill with junk
  return (void*)r;
}

Buffer Cache

1. 修改bcache结构体

#define NBUCKETS 13

struct { 
  struct spinlock lock[NBUCKETS];
  struct buf buf[NBUF];

  // Linked list of all buffers, through prev/next.
  // Sorted by how recently the buffer was used.
  // head.next is most recent, head.prev is least.
  struct buf head[NBUCKETS];
} bcache;

2. 修改 bget

static struct buf*
bget(uint dev, uint blockno)
{
  struct buf *b;
  int i = hash(blockno);


  acquire(&bcache.lock[i]);

  // Is the block already cached?
  for(b = bcache.head[i].next; b != &bcache.head[i]; b = b->next){
    if(b->dev == dev && b->blockno == blockno){

      b->refcnt++;
      release(&bcache.lock[i]);
      acquiresleep(&b->lock);
      return b;
    }
  }

  // Not cached.
  // Recycle the least recently used (LRU) unused buffer.
  for(b = bcache.head[i].prev; b != &bcache.head[i]; b = b->prev){
    if(b->refcnt == 0) {
      b->dev = dev;
      b->blockno = blockno;
      b->valid = 0;
      b->refcnt = 1;
      release(&bcache.lock[i]);
      acquiresleep(&b->lock);
      return b;
    }
  }
  for(int j = (i+1) % NBUCKETS; j != i; j = (j+1) %NBUCKETS) {
    acquire(&bcache.lock[j]);
    for(b = bcache.head[j].prev; b != &bcache.head[j]; b = b->prev){
      if(b->refcnt == 0) {
        b->dev = dev;
        b->blockno = blockno;
        b->valid = 0;
        b->refcnt = 1;
        b->next->prev = b->prev;
        b->prev->next = b->next;
        release(&bcache.lock[j]);
        b->next = bcache.head[i].next;
        b->prev = &bcache.head[i];
        bcache.head[i].next->prev = b;
        bcache.head[i].next = b;
        release(&bcache.lock[i]);
        acquiresleep(&b->lock);
        return b;
      }
    }
    release(&bcache.lock[j]); //记得释放锁,因为有可能走不进 cnt == 0 的if语句

  }

  panic("bget: no buffers");
}

3. 修改brels

void
brelse(struct buf *b)
{
  if(!holdingsleep(&b->lock))
    panic("brelse");
  releasesleep(&b->lock);

  int i = hash(b->blockno);
  acquire(&bcache.lock[i]);
  b->refcnt--;
  if (b->refcnt == 0) {
    // no one is waiting for it.
    b->next->prev = b->prev;
    b->prev->next = b->next;
    b->next = bcache.head[i].next;
    b->prev = &bcache.head[i];
    bcache.head[i].next->prev = b;
    bcache.head[i].next = b;
  }
  
  release(&bcache.lock[i]);
}

4. 修改bpin和bunpin

void
bpin(struct buf *b) {
  int i = hash(b->blockno);
  acquire(&bcache.lock[i]);
  b->refcnt++;
  release(&bcache.lock[i]);
}

void
bunpin(struct buf *b) {
  int i = hash(b->blockno);
  acquire(&bcache.lock[i]);
  b->refcnt--;
  release(&bcache.lock[i]);
}

5. 修改binit

void
binit(void)
{
  struct buf *b;

  initlock(&bcache.lock, "bcache");

  // Create linked list of buffers
  for(int i = 0; i < NBUCKETS; i++) {
    bcache.head[i].prev = &bcache.head[i];
    bcache.head[i].next = &bcache.head[i];
  }

  for(b = bcache.buf; b < bcache.buf+NBUF; b++){
    b->next = bcache.head[0].next;
    b->prev = &bcache.head[0];
    initsleeplock(&b->lock, "buffer");
    bcache.head[0].next->prev = b;
    bcache.head[0].next = b;
  }
}

7. 添加hash

int hash(int blockno) {
  return blockno % NBUCKETS;
}

8. 运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值