Week 09 PintOS UserProgram
Argument Passing
swift-shame-3ee.notion.site
Argument Passing
프로시저 실행 순서
- user app은 %rdi, %rsi, %rdx, %rcx, %r8, %r9의 값을 argument로 가져온다
- caller는 return address를 자신의 stack에 저장한 후에 callee로 간다(CALL instruction)
- callee 실행
- callee가 return이 있으면 %rax에 저장
- return address으로 다시 돌아감(RET instruction)
%rdi(첫번째 인자) → int argc
%rci(두번째 인자) → char **argv
argv는 user stack에 저장 및 stack pointer 위치 수정
User Memory Access
address가
- NULL
- Kernel memory
- VM에 속하지 않을 때
접근을 거부
System Calls
Interrupt Frame
context switching을 하기 전에 자신의 register 상태를 저장하는 struct
context switching은 두 가지 경우에 발생
preemption에 의해 cpu에서 벗어날 경우(서로 다른 thread끼리 context switching)
struct thread 안의 interrupt_frame tf에 저장
user mode에서 kernel mode로 넘어가는 경우(한 thread 안에서 context switching)
struct thread를 만들때 page 크기(4kb)를 할당 받음
→ struct thread를 저장하고 남은 부분을 kernel stack으로 활용
→ 이 곳에 interrupt_frame을 저장
System call
- user process가 system call 호출
- lib/user/system.c에 있는 매크로를 통해서%rdi, %rsi, %rdx, %r10, %r8, %r9 → 순서대로 인자
- register 세팅 후에 system_call_handler 호출(user mode → kernel mode)
- %rax → system_call_num
- userprog/system.c에 있는 system_call_handler에 의해 호출한 system call 실행
- system call 실행 후 다시 user process로 return(kernel mode → user mode)
void halt(void)
pintos 종료
void exit(int status)
process 종료
system call에 의한 종료는 정상 종료
그 이외에 오류로 인한 종료는 비정상 종료 → status = -1
pid_t fork(const char *thread name, struct interrupt_fram *if)
자식 process를 만들어서 자신과 똑같은 file을 fork system call을 호출한 시점과 똑같은 상태로 실행시킴 → 부모 process가 system call로 kernel mode 넘어가기 전에 저장한 if을 자식 process에게 전달 → 전달 받은 if를 기반으로 do_iretq 실행
자식 process를 만드는데 실패하면 TID_ERROR(-1) return
자식 process는 return 값으로 0을 받는다
int exec(const char *cmd_line)
현재 thread를 입력 받은 file을 실행하도록 변경
실패하면 exit(-1)
cmd_line은 file 이름 + 인자로 구성(argument passing 할 때와 같음)
입력 받은 cmd_line이 race condition이 될 수 있기 때문에 따로 복사해서 사용
int wait(pid_t pid)
부모 process가 자식 process가 종료될 때까지 기다리는 system call
부모 process는 종료된 자식 process의 exit status를 전달 받아서 return
bool create(const char *file, unsigned initial_size)
size 크기의 새로운 file을 생성
open하지 않음
bool remove(const char *file)
file 삭제
int open(const char *file)
file을 open해서 struct file을 만들고 process의 file descripter table에 저장하고 file descripter(table의 index)를 return
fdt의 index 0, 1은 각각 표준 입력, 표준 출력이다
fdt[0], fdt[1]의 값은 1, 2를 각각 넣어서 사용한다 → struct file pointer 배열이지만 주소값을 int 값처럼 쓴다
int filesize(int fd)
file의 size를 return
int read(int fd, void *buffer, unsigned size)
fd의 현재 position에서 size만큼 buffer로 읽어온다
fd가 0인 경우 표준 입력을 받는다(input_getc())
read를 semaphore로 write와 함께 상호배제하도록 만든다
실제로 읽은 bytes를 return 한다
int write(int fd, const void *buffer, unsigned size)
fd에서 buffer의 내용을 size만큼 쓴다
fd가 1인 경우 표준 출력을 받는다(putbuf())
read를 semaphore로 write와 함께 상호배제하도록 만든다
실제로 쓴 bytes를 return 한다
void seek(int fd, unsigned position)
fd의 position을 입력받은 position으로 변경
unsigned tell(int fd)
fd의 현재 position을 return
void close(int fd)
open한 file을 닫고 fdt에서 삭제한다
process가 종료될 때 fdt의 모든 file을 close해야한다
dup2 구현시 표준 입력(STDIN), 표준 출력(STDOUT), 복사된 수(struct file→dup_cnt)을 낮추고 더 이상 못 낮추면 close를 실행한다
int dup2(int oldfd, int newfd)
newfd가 oldfd와 같은 struct file을 가리키도록 한다
표준 입력과 표준 출력도 복제 가능
fork 과정에서 부모 process의 fdt를 복사할때 dictionary struct를 만들어서 복사한다
Process Termination Message
system call exit를 실행할 때 exit status와 함께 종료를 알리는 출력을 한다
Denying Writes to Executables
실행 중인 file에 write을 막아야한다
write을 막는 것은 file.c 의 file_deny_write()를 활용한다
처음 exec에서 load를 할 때 load 후에 실행한 file을 닫지 않고 write를 막는다 → file을 닫으면 자동으로 쓰기가 가능해진다(file_close() 에서 file_allow_write()를 하고 닫음) → process가 종료될 때 실행 중인 file을 닫는다
'SW정글 > OS' 카테고리의 다른 글
[SW정글] Week 11 개발일지 (0) | 2023.01.30 |
---|---|
[SW정글] Week 10 개발일지 (0) | 2023.01.30 |
[SW정글] Week 08 개발일지 (0) | 2023.01.30 |