본문 바로가기
SW사관학교 정글 4기/pintos

load_segment

by g0n1 2022. 6. 11.
728x90

코드

static bool
load_segment (struct file *file, off_t ofs, uint8_t *upage,
		uint32_t read_bytes, uint32_t zero_bytes, bool writable) {
	ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
	ASSERT (pg_ofs (upage) == 0);
	ASSERT (ofs % PGSIZE == 0);

	file_seek (file, ofs);
	while (read_bytes > 0 || zero_bytes > 0) {
		/* Do calculate how to fill this page.
		 * We will read PAGE_READ_BYTES bytes from FILE
		 * and zero the final PAGE_ZERO_BYTES bytes. */
		size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
		size_t page_zero_bytes = PGSIZE - page_read_bytes;

		/* Get a page of memory. */
		uint8_t *kpage = palloc_get_page (PAL_USER);
		if (kpage == NULL)
			return false;

		/* Load this page. */
		if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) {
			palloc_free_page (kpage);
			return false;
		}
		memset (kpage + page_read_bytes, 0, page_zero_bytes);

		/* Add the page to the process's address space. */
		if (!install_page (upage, kpage, writable)) {
			printf("fail\n");
			palloc_free_page (kpage);
			return false;
		}

		/* Advance. */
		read_bytes -= page_read_bytes;
		zero_bytes -= page_zero_bytes;
		upage += PGSIZE;
	}
	return true;
}

목적

file 내에서 ofs부터 시작해 upage라는 주소공간에 세그먼트를 불러들입니다. 이 함수를 통해 초기화된 페이지들에 대해서 만약 writable이 true로 넘어왔다면 writable해야 하고, 그렇지 않으면 read-only여야 합니다. 만약 메모리 할당 에러나 디스크 읽기 에러가 난 경우에는 false를 반환합니다.

요약: 파일[ofs:] 로 읽어서 페이지 할당받고 가상->물리 매핑도 추가해줌.

루틴

 

호출되는 곳

/userprog/process.c의 load 함수

case PT_LOAD:
	if (validate_segment (&phdr, file)) {
		bool writable = (phdr.p_flags & PF_W) != 0;
		uint64_t file_page = phdr.p_offset & ~PGMASK;
		uint64_t mem_page = phdr.p_vaddr & ~PGMASK;
		uint64_t page_offset = phdr.p_vaddr & PGMASK;
		uint32_t read_bytes, zero_bytes;
		if (phdr.p_filesz > 0) {
			/* Normal segment.
			 * Read initial part from disk and zero the rest. */
			read_bytes = page_offset + phdr.p_filesz;
			zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE)
					- read_bytes);
		} else {
			/* Entirely zero.
			 * Don't read anything from disk. */
			read_bytes = 0;
			zero_bytes = ROUND_UP (page_offset + phdr.p_memsz, PGSIZE);
		}
		if (!load_segment (file, file_page, (void *) mem_page,
					read_bytes, zero_bytes, writable))
			goto done;
	}
  • PT_LOAD : ELF의 타입이다. PT_LOAD는 loadable한 elf파일. 더 많은 정보는 [ELF1] 1-2를 보라고 한다. 
  • validate_segment : PHDR이 valid하고 loadable segment를 가리키는지 확인한다.
  • PHDR : ELF 내 세그먼트의 종류, ELF header, Program header, Section header가 있다. (참고할 곳)

 

728x90

댓글