[PintOS] Project 2 - User Programs 3

Quro·2024년 5월 25일
0

OS

목록 보기
4/6
post-thumbnail

User Memory Access

시스템 콜을 구현하기 위해 유저의 가상 주소 공간에 접근할 수 있는 방법을 제시해줘야 한다

👉 시스템 콜의 인자로 들어오는 모든 포인터 값을 검사
void check_address(void* uaddr) {
	struct thread *cur = thread_current();
	if (uaddr == NULL || is_kernel_vaddr(uaddr) || pml4_get_page(cur->pml4, uaddr) == NULL) {
		exit(-1);
	}
}
  • NULL pointer(유효하지 않은 포인터)이거나
  • 커널 메모리에 대한 포인터를 가리키거나
  • 맵핑되지 않은 vm에 대한 포인터라면
  • 프로세스 종료

System Call

👉 pintOS는 시스템 콜 핸들러가 구현되어 있지 않아 시스템 콜이 처리되지 않는다. pintOS의 시스템 콜 메커니즘을 이해하고 시스템 콜 핸들러를 구현해야 한다.
  • 시스템 콜(halt, exit, create, remove 등)을 구현하고 시스템 콜 핸들러를 통해 호출
  • %rax 는 system call number
  • 네 번째 argument는 %rcx가 아니라 %r10 이다
  • 따라서 syscall_handler() 가 제어권을 잡으면, system call number는 %rax 안에 있게 되고, arguments들은 %rdi, %rsi, %rdx, %r10, %r8, %r9 순서로 전달

pintOS의 시스템 콜 호출 과정

  • 유저 프로그램에서 write() 시스템 콜 호출
  • pintos/lib/user/syscall.c 에서 write() 함수 호출
int
write (int fd, const void *buffer, unsigned size) {
	return syscall3 (SYS_WRITE, fd, buffer, size);
}
  • SYS_WRITE는 include/lib/syscall-nr.h 에 enum으로 정의(SYS_WRITE = 10)
  • 이 시스템 콜 번호와 받아온 인자값들을 가지고 syscall3을 호출
    • 이때의 syscall 뒤에 붙는 숫자는 인자(argument)의 개수
  • syscall3 은 syscall을 호출
  • 레지스터에 인자값을 넣고, 어셈블리어로 syscall을 호출 → syscall-entry.s 로 이동

  • rsp(stack pointer) 값을 바꿔줌으로써 커널 스택으로 진입

  • syscall_handler로 이동 후 시스템 콜 함수 호출
int write(int fd, const void *buffer, unsigned size) {
    check_address(buffer);
    int bytes_write = 0;
    if (fd == STDOUT_FILENO) {
        putbuf(buffer, size);
        bytes_write = size;
    } else {
        if (fd < 2)
            return -1;
        struct file *file = process_get_file(fd);
        if (file == NULL)
            return -1;
        lock_acquire(&filesys_lock);
        bytes_write = file_write(file, buffer, size);
        lock_release(&filesys_lock);
    }
    return bytes_write;
}

시스템 콜 write함수 호출 완료 !!

profile
개발합니다

0개의 댓글