09_pintos_VM_memory_mapped_file

신치우·2022년 12월 12일

data_structure_and_Pintos

목록 보기
31/36

Memory mapped page를 구현할 것입니다.
anonymous page와 다르게 Memory mapped page는 file page 기반입니다.
page fault가 발생하면 물리 프레임이 즉시 할당되고 content가 file에서 memory로 복사됨
memory에 mapping 된 페이지가 unmapped 또는 swap out되면 content의 모든 변경 사항은 file에 저장됨

memory에 mapping된 page도 anonymous page 처럼 lazy_load로 할당되어야함

mmap 의 목적은 file의 data를 가상메모리 주소공간에 복사를 하는 것

memory에 mapping된 file을 위한 시스템콜 MMAP, MUNMAP을 먼저 구현한다
기존 syscall handler 부분에 system call을 받는 부분을 추가해주고

    case SYS_MMAP:
      f->R.rax = mmap(a1, a2, a3, a4, a5);
      break;
    case SYS_MUNMAP:
      munmap(a1);
      break;

mmap 을 만들어준다 -- fd로 열린 파일의 오프셋 바이트부터 length 바이트 만큼을 프로세스의 가상주소공간의 주소 addr 에 매핑 합니다.

//syscall.c
void
*mmap (void *addr, size_t length, int writable, int fd, off_t offset){
  if(offset % PGSIZE != 0 ) // 우리는 모든걸 PGSIZE에 맞춰서 사용하기 때문에 PGSIZE가 아닌 경우 return NULL
    return NULL;

  if (pg_round_down(addr) != addr || is_kernel_vaddr(addr) || addr == NULL || (long long)length <=0){
  // pg_round_down(addr) != addr --> input된 addr이 page 주소가 맞는지 확인
  // is_kernel_vaddr (addr) --> addr 가 kernel에 위치하고 있는지
  // addr == NULL --> addr이 NULL 인지
  // (long long) length <= 0 --> input 된 크기가 0 이상인지
    return NULL;
  }
  
  if (fd == 0 || fd == 1){
    // fd 가 0이나 1이라는 의미는 STDIN, STDOUT 이라는 의미이니깐 들어오면 안되는 애가 들어온거 --> exit로 보내버림
    exit_handler(-1);
  }
  
  if(spt_find_page(&thread_current()->spt, addr)){
    // addr 가 spt table에 존재하고 있는지 확인
    return NULL;
  }
  
  struct file * target = find_file_using_fd(fd); // fd가 존재하는거니깐 fd에 맞는 file을 찾고

  if(target == NULL)
    return NULL;
  
  void *ret = do_mmap(addr, length, writable, target, offset); 
  //fd로 열린 파일의 오프셋 바이트부터 length 바이트 만큼을 프로세스의 가상주소공간의 주소 addr 에 매핑 합니다

  return ret;
}

do_mmap -- 실제 mapping이 일어나는 공간

file_reopen 우리는 이미 열린 파일을 사용하게 되는데 reopen 함수를 통해서 해당 파일을 독립적으로 사용할 수 있게 함

/* Do the mmap */
// fd로 열린 파일의 오프셋 바이트부터 length 바이트 만큼을 프로세스의 가상주소공간의 주소 addr 에 매핑 합니다
void *
do_mmap (void *addr, size_t length, int writable, struct file *file, off_t offset) {
	struct file *mfile = file_reopen(file); // 해당 파일의 소유권을 가져와서 새 파일을 반환함 - 매핑에 대해 개별적이고 독립적인 참조를 얻음

	// load_segment와 동일함 -- 하지만 load segment는 read_byte 가 input으로 들어오지만 여기선 들어오지 않음
	// 그에 따라서 실제 사용할 data를 구성해줘야함
	void *ori_addr = addr;
	size_t read_byte = length > file_length(file) ? file_length(file) : length;
	size_t zero_byte = PGSIZE - read_byte % PGSIZE;

	while(read_byte > 0 || zero_byte > 0){
		size_t page_read_byte = read_byte < PGSIZE ? read_byte : PGSIZE;
		size_t page_zero_byte = PGSIZE - page_read_byte;

		struct container *container_p = (struct container *)malloc(sizeof(struct container));
		container_p->file = mfile;
		container_p->offset = offset;
		container_p->read_byte = page_read_byte;
		
		if(!vm_alloc_page_with_initializer(VM_FILE, addr, writable, lazy_load_segment, container_p)){
			return NULL;
		}

		read_byte -=page_read_byte;
		zero_byte -=page_zero_byte;
		addr +=PGSIZE;
		offset +=page_read_byte;
	}
	return ori_addr;
}

munmap

  • 지정된 주소는 아직 매핑 해제되지 않은 동일한 프로세서의 mmap에 대한 이전 호출에서 반환된 가상 주소여야 합니다.
  • 파일을 닫거나 제거해도 해당 매핑이 매핑 해제되지 않습니다.
  • 우리는 file을 file_reopen 함수를 통해서 open했기 때문에 독립적으로 사용이 가능
  • 생성된 매핑은 Unix 규칙에 따라 munmap이 호출되거나 프로세스가 종료될 때까지 유효합니다.
void 
munmap (void *addr){
  do_munmap(addr);
}

do_munmap

  • 지정된 address를 pml4 에서 제거함
void
do_munmap (void *addr) {
	while (true){
		struct page *page_ = spt_find_page(&thread_current()->spt, addr); // 해당 address에 맞는 page를 찾음

		if(page_ == NULL) // page가 NULL이면 할 필요가 없으니깐
			break;

		struct container * aux = (struct container *) page_->uninit.aux; // page_의 aux를 형변환 한다 -- 내부 데이터를 다 지울거야

		if(pml4_is_dirty(thread_current()->pml4, page_->va)){ // pml4 의 가상페이지에 page_->va 가 dirty 인 경우 (즉, page_->va 가 설치된 후 페이지가 수정된 경우 true를 반환)
			file_write_at(aux->file, addr, aux->read_byte, aux->offset); // addr에 있는 정보를 aux->offset부터 read_byte만큼 aux->file에 씁니다
			pml4_set_dirty(thread_current()->pml4, page_->va, 0); // pml4 의 가상페이지에 있는 page_->va의 dirty 비트를 dirty 로 설정
		}

		pml4_clear_page(thread_current()->pml4, page_->va); // pml4 에 존재하는 page_->va를 존재하지 않음으로 표기함 --> 추후에 접근하려고 하면 error 가 발생함
		addr +=PGSIZE; // page를 지운 후 addr를 다음 page의 시작지점으로 옮김
	}
}
profile
https://shin8037.tistory.com/

0개의 댓글