Lab 11: mmap

struct vma*
get_vma(struct vma* now, int length){
  uint64 max = TRAPFRAME;//起始地址
  int target = -1;

  for(int i = 0; i < MAX_VMA; i++){
    if(target == -1 && now[i].length == 0){
      //空闲的vma
      target = i;
      continue;
    }
    if(now[i].length == 0)
      continue;
    
    if(max > now[i].addr)
      max = now[i].addr; //找到最小地址
  }
  
  uint64 head_addr = PGROUNDDOWN(max - length);

  now[target].addr = head_addr;
  now[target].length = length;
  now[target].offset = 0;
  // printf("length = %d pages\n", length / PGSIZE);
  return &now[target];
}

uint64
sys_mmap(void){
  // void *addr, int length, int prot, int flags, int fd
  uint64 addr;
  int length, prot, flags, fd, offset;
  struct file* f;

  if(argaddr(0, &addr) < 0 ||argint(1, &length) < 0 || argint(2, &prot) < 0 || argint(3, &flags) < 0 || argfd(4, &fd, &f) < 0 || argint(5, &offset) < 0){
    return -1;
  }
  if(addr || offset)
    return -1;

  //判断权限
  if(!f->writable && (prot & PROT_WRITE) && (flags & MAP_SHARED)){
    return -1;
  }

  if(length <= 0)
    return -1;
  
  struct proc* p = myproc();
  struct vma* now = get_vma(p->vmas, length);

  now->f = f;
  now->flags = flags;
  now->prot = prot;

  filedup(f);

  return now->addr;
}


uint is_vma(uint64 addr){
  struct proc* now = myproc();
  struct vma* now_vma = 0;
  for(int i = 0; i < MAX_VMA; i++){
    if(addr >= now->vmas[i].addr && addr < now->vmas[i].addr + now->vmas[i].length){
      now_vma = &now->vmas[i];
      break;
    }
  }
  if(now_vma == 0)
    return -1;
  addr = PGROUNDDOWN(addr);
  uint64 pa = (uint64)kalloc();
  memset((void *)pa, 0, PGSIZE);
  int perm = PTE_U | PTE_V;
  if(now_vma->prot & PROT_READ){
    perm |= PTE_R;
  }
  if(now_vma->prot & PROT_WRITE){
    perm |= PTE_W;
  }
  if(now_vma->prot & PROT_EXEC){
    perm |= PTE_X;
  }
  ilock(now_vma->f->ip);
  readi(now_vma->f->ip, 0, pa, addr - now_vma->addr, PGSIZE);
  iunlock(now_vma->f->ip);
  
  mappages(now->pagetable, addr, PGSIZE, pa, perm);
  return 0;
}
if(r_scause() == 15 || r_scause() == 13){
    uint64 fault_addr = r_stval();
      if (is_vma(fault_addr) ==  -1){
          p->killed = 1;
      }
  } 
uint64 
sys_munmap(void){
  // munmap(addr, length)
  uint64 addr;
  int length;
  if(argaddr(0, &addr) < 0 ||argint(1, &length) < 0){
    return -1;
  }

  struct proc* p = myproc();
  struct vma* now_vma = 0;
  //1.找到那个vma
  for(int i = 0; i < MAX_VMA; i++){
    if(addr >= p->vmas[i].addr && addr < p->vmas[i].addr + p->vmas[i].length){
      now_vma = &p->vmas[i];
      break;
    }
  }

  // 检查是否找到 VMA
  if(!now_vma){
    return -1; // addr 不在任何 VMA 的范围内
  }

  // 检查 length 是否超出 VMA 的范围
  if(addr + length > now_vma->addr + now_vma->length){
    length = now_vma->addr + now_vma->length - addr;
  }

  struct file* f = now_vma->f;
  //2.判断是否写入
  if(now_vma->flags & MAP_SHARED){
    begin_op();
    ilock(f->ip);
    // writei(f->ip, 1, addr, addr - now_vma->addr + now_vma->offset, length);
    writei(f->ip, 1, addr, addr - now_vma->addr + now_vma->offset, now_vma->length);
    iunlock(f->ip);
    end_op();
  }
  //3.更改vma
  now_vma->length -=length;
  if(addr == now_vma->addr){
    now_vma->offset += length;
    now_vma->addr += length;
  }
  //4.解除映射
  //  释放空间
  uvmunmap(p->pagetable, addr, length / PGSIZE, 1);

  //4.空间完全被释放,关闭文件
  if(now_vma->length == 0){
    fileclose(f);
    now_vma->addr = 0;
    now_vma->f = 0;
    now_vma->flags = 0;
    now_vma->prot = 0;
    now_vma->offset = 0;
  }
  return 0;
}
if((*pte & PTE_V) == 0)
      continue;
//fork
for(int i = 0; i < MAX_VMA; i++){
    if(p->vmas[i].length != 0){
      np->vmas[i] = p->vmas[i];
      filedup(p->vmas[i].f);
    }
  }
//exit

for(int i = 0; i < MAX_VMA; i++){
    if(p->vmas[i].addr != 0){
      uvmunmap(p->pagetable, p->vmas[i].addr, p->vmas[i].length / PGSIZE, 1);
    }
    if(p->vmas[i].f){
      fileclose(p->vmas[i].f);
    }
    p->vmas[i].addr = 0;
    p->vmas[i].f = 0;
    p->vmas[i].flags = 0;
    p->vmas[i].prot = 0;
    p->vmas[i].offset = 0;
  }

  // Close all open files.
  for(int fd = 0; fd < NOFILE; fd++){
    if(p->ofile[fd]){
      struct file *f = p->ofile[fd];
      fileclose(f);
      p->ofile[fd] = 0;
    }
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值