[SW사관학교 정글]66일차 TIL

김승덕·2022년 11월 24일
0

SW사관학교 정글 5기

목록 보기
106/150
post-thumbnail

System call

과제 설명

과제 목표

시스템 콜 핸들러 및 시스켐 콜(halt, exit, create, remove) 구현

과제 설명

핀토스는 시스템 콜 핸들러가 구현되어 있지 않아 시스템 콜이 처리되지 않음
핀토스의 시스템 콜 메커니즘을 이해하고 시스템 콜 핸들러를 구현
시스템 콜(halt, exit, create, remove)을 구현하고 시스템 콜 핸들러를 통해 호출

process related : halt, exit, exec, wait
file related : create, remove, open, filesize, read, write, seek, tell, close

수정 파일

/threads/thread.*

/userprog/syscall.*

/userprog/process.*

시스템 콜이란?

💡 유저 프로그램이 OS에 쉽게 접근할 수 있도록 만든 인터페이스

사용자 모드 프로그램이 커널 기능을 사용할 수 있도록 함
시스템 콜은 커널모드에서 실행되고, 처리 후 사용자 모드로 복귀됨
시스템 호출의 핵심은 하드웨어 인터럽트가 생성되어 시스템 호출이 이루어짐에 따라 실행 모드의 우선순위가 특수 모드로 올라간다는 것이다.

Call process of System call(pintos)

먼저 user 영역과 kernel 영역은 나누어져있다. (나누어져 있는 이유는 안전때문이다.)

user가 write함수를 사용했다고 가정해보자.

그럼 진행상황은 아래와 같다.

  1. user가 write함수 사용
  2. syscall.cwrite이라는 함수가 있다. 이 함수는 syscall3 함수를 반환한다.(syscall뒤의 숫자 3의 의미는 파라미터의 개수이다.)
  3. syscall3함수는 각각의 인자를 push하고(인자가 3개이므로 3개를 push) number(이것은 system call number이다)를 push한다. 그리고 0x30이라는 주소가 나오는데 이는 interrupt vector table에서 system_call()함수가 있는 주소이다. system_call()를 호출한다.
  4. 이제 이 system_call()을 구현하면 된다.

System call handler

system call number는 /lnclude/lib/syscall_nr.h에 있다.

#ifndef __LIB_SYSCALL_NR_H
#define __LIB_SYSCALL_NR_H

/* System call numbers. */
enum {
	/* Projects 2 and later. */
	SYS_HALT,                   /* Halt the operating system. */
	SYS_EXIT,                   /* Terminate this process. */
	SYS_FORK,                   /* Clone current process. */
	SYS_EXEC,                   /* Switch current process. */
	SYS_WAIT,                   /* Wait for a child process to die. */
	SYS_CREATE,                 /* Create a file. */
	SYS_REMOVE,                 /* Delete a file. */
	SYS_OPEN,                   /* Open a file. */
	SYS_FILESIZE,               /* Obtain a file's size. */
	SYS_READ,                   /* Read from a file. */
	SYS_WRITE,                  /* Write to a file. */
	SYS_SEEK,                   /* Change position in a file. */
	SYS_TELL,                   /* Report current position in a file. */
	SYS_CLOSE,                  /* Close a file. */

	/* Project 3 and optionally project 4. */
	SYS_MMAP,                   /* Map a file into memory. */
	SYS_MUNMAP,                 /* Remove a memory mapping. */

	/* Project 4 only. */
	SYS_CHDIR,                  /* Change the current directory. */
	SYS_MKDIR,                  /* Create a directory. */
	SYS_READDIR,                /* Reads a directory entry. */
	SYS_ISDIR,                  /* Tests if a fd represents a directory. */
	SYS_INUMBER,                /* Returns the inode number for a fd. */
	SYS_SYMLINK,                /* Returns the inode number for a fd. */

	/* Extra for Project 2 */
	SYS_DUP2,                   /* Duplicate the file descriptor */

	SYS_MOUNT,
	SYS_UMOUNT,
};

#endif /* lib/syscall-nr.h */

requirement for system call handler

  • system call handler가 system call number를 사용하여 system call을 부르도록 만들어라
  • (중요)parameter 리스트에서 포인터의 유효성을 체크해라
    • 이 포인터들은 반드시 user area에 있어야한다.
    • 만약 이 포인터들이 유효하지 않으면 page fault이다.
  • user stack에서 kernel로 argument를 복사하라
  • rax 레지스터에서 system call의 반환값을 저장하라

Address Validation

user는 system call을 통해 유효하지 않은 포인터를 통과할수있다.

  • null 포인터이거나, 가상 메모리에 매핑되지 않은 포인터
  • 커널 가상메모리 주소 공간에 대한 포인터

os는 위의 두 경우에 program을 kill해야한다.

커널은 유효하지 않은 포인터로부터 보호되어야하고 커널 또는 다른 running 프로세스에 해를 가하지 않으며 프로세스를 종료해야한다.

어떻게 보호하느냐?

방법 1 : user 제공 포인터의 유효성을 확인해라

방법 2 : PHYS_BASE 아래의 유저 포인터만을 확인해라 → 실제 os에서 쓰이는 방법

  • page_fault() 코드를 수정해서 유효하지 않은 포인터를 처리해라.
  • 첫번째 방법보다 빠르다.

Accessing user memory

이 두 경우 모두 leak resource이 일어날 수 있다.

lock 후 unlock 안된 경우, malloc 후 free 안된경우 시간이 지자면 page fault가 발생할 수 있다.

이러한 문제를 해결하기 위해서 위의 방법 1과 방법 2의 해결 방법이 다르다.

방법 1 : os가 해결해주니까 괜찮다.

방법 2

메모리접근에서의 에러 코드를 반환할 방법이 없다.

get_user함수와 put_user함수를 사용할수있다.
get_user : 사용자 가상 메모리에서 byte를 읽어옴
put_user : 사용자 주소에 1 byte를 씀

void halt(void)

  • 핀토스 shutdown(halt 함수가 불려졌을때만 shutdown 되어야함)
  • shutdown_power_off(void) 함수를 사용해야함

void exit(int status)

  • 프로세스 종료
  • thread_exit(void) 함수 사용
  • “프로세스 이름: exit(상태)”를 printf해야한다.

pid_t exec(const char *cmd_line)

  • 자식 프로세스를 만들고 cmd_line에 적은 프로그램을 실행한다.
  • 유닉스의 exec와 다르다. 오히려 핀토스의 exec는 fork와 exec의 콤비네이션 느낌이다.

int wait(pid_t pid)

  • 프로세스 id가 pid(인자)인 자식 프로세스가 종료될때까지 기다린다.

process hierarchy(프로세스 계층)

Augment the existing process with the process hierarchy.(먼말인지 모르겠음...)

부모와 자식간의 관계를 표현하는 법

  • 부모 프로세스한테 포인터 : struct thread*
  • sibling한테 포인터 : struct list
  • 자식한테 포인터 : struct list_elem

자식한테 포인터를 주는 방법은 많지만 모든 자식한테 포인터를 주는것은 적절치않다.

sibling list의 tail에 포인터를 주고, sibling list의 head에 포인터를 주어라

(there are many to implement pointers to children

but it is not reasonable to install all the pointers to all child

maintain pointer tail of the sibling list and head of the sibling list)

profile
오히려 좋아 😎

0개의 댓글