시스템 콜 핸들러 및 시스켐 콜(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에 쉽게 접근할 수 있도록 만든 인터페이스
사용자 모드 프로그램이 커널 기능을 사용할 수 있도록 함
시스템 콜은 커널모드에서 실행되고, 처리 후 사용자 모드로 복귀됨
시스템 호출의 핵심은 하드웨어 인터럽트가 생성되어 시스템 호출이 이루어짐에 따라 실행 모드의 우선순위가 특수 모드로 올라간다는 것이다.
먼저 user 영역과 kernel 영역은 나누어져있다. (나누어져 있는 이유는 안전때문이다.)
user가 write함수를 사용했다고 가정해보자.
그럼 진행상황은 아래와 같다.
write
함수 사용syscall.c
에 write
이라는 함수가 있다. 이 함수는 syscall3
함수를 반환한다.(syscall
뒤의 숫자 3의 의미는 파라미터의 개수이다.)syscall3
함수는 각각의 인자를 push
하고(인자가 3개이므로 3개를 push) number
(이것은 system call number이다)를 push
한다. 그리고 0x30이라는 주소가 나오는데 이는 interrupt vector table에서 system_call()
함수가 있는 주소이다. system_call()
를 호출한다.system_call()
을 구현하면 된다.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 */
rax
레지스터에서 system call의 반환값을 저장하라user는 system call을 통해 유효하지 않은 포인터를 통과할수있다.
os는 위의 두 경우에 program을 kill해야한다.
커널은 유효하지 않은 포인터로부터 보호되어야하고 커널 또는 다른 running 프로세스에 해를 가하지 않으며 프로세스를 종료해야한다.
어떻게 보호하느냐?
방법 1 : user 제공 포인터의 유효성을 확인해라
방법 2 : PHYS_BASE 아래의 유저 포인터만을 확인해라 → 실제 os에서 쓰이는 방법
이 두 경우 모두 leak resource이 일어날 수 있다.
lock 후 unlock 안된 경우, malloc 후 free 안된경우 시간이 지자면 page fault가 발생할 수 있다.
이러한 문제를 해결하기 위해서 위의 방법 1과 방법 2의 해결 방법이 다르다.
방법 1 : os가 해결해주니까 괜찮다.
방법 2
메모리접근에서의 에러 코드를 반환할 방법이 없다.
get_user함수와 put_user함수를 사용할수있다.
get_user : 사용자 가상 메모리에서 byte를 읽어옴
put_user : 사용자 주소에 1 byte를 씀
Augment the existing process with the process hierarchy.(먼말인지 모르겠음...)
부모와 자식간의 관계를 표현하는 법
자식한테 포인터를 주는 방법은 많지만 모든 자식한테 포인터를 주는것은 적절치않다.
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)