Pintos project 2

do young Lee·2023년 5월 9일
0

swjungle

목록 보기
3/4

pintos 2주차를 진행하면서 어려웠던 개념이나 구현시 실수 했던 부분들에 대한 내용을 기록하고자 글을 남긴다.

Argument passing

  • 구현 사항
    • user stack 영역에 정해진 규약에 따라 전달 받은 argument들을 저장 해야한다
  • 주의 사항
    • user stack 영역 시작 주소는 kernel 영역의 저장되어있는 interrupt frame에 rsp 필드에 저장되어 있고, stack은 아래 방향으로 grow up 하기 때문에 값을 복사할떄 복사할 양만큼 감소 시킨 부분부터 복사 해야한다.
    • system call 을 구현하기 전까지는 실제로 해당 실행 파일에 인자들을 전달해 실행하는것이 아니기 때문에 hex_dump 라는 함수를 사용해서 출력 결과를 manual 하게 확인 해야한다.
    • Augument passing 이후 hex_dump 함수의 결과
  • 추가적으로 고려 해야할 부분
    • command line 으로 입력 받은 문자열을 parsing 해서 각각의 인자들을 문자열 배열에 저장 했는데 이떄 임시로 그 배열의 크기를 10으로 선언함 → 해당 부분을 적절히 제한하는 방향으로 수정 필요

System call

  • system call 이 호출되는 흐름
    1. user program 이 create, remove, open, read, write 와 같은 system call 함수를 호출한다.
    2. syscall interrupt 가 발생
    3. cpu 레지스터에 있는 값들을 kernel 영역에 있는 interrupt frame에 저장 (64bit 버전의 pintos 에 추가되어있는 syscall 이라는 어셈블리어가 해당 역활을 수행)
    4. syscall_handler 함수 호출
      • user program이 syscall_handler 함수를 호출할때 argument들은 interrupt frame의 필드에 저장되어 전달된다.
      1. syscall_number 는 interrupt frame의 %rax
      2. argumernts 들은 %rdi, %rsi, %rdx, %r10, %r8, %r9 순서로 전달된다.
  • filesys 관련 syscall 들을 처리하기 위해서 thread 구조체의 필드에 file descriptor table 과 마지막 file descriptor를 나타내는 값 두가지가 추가된다. → open 한 파일들에 대한 table
struct thread {
// ...
// ...
// ...
// ...
	
struct file **fdt; /* File descriptor table */	
int next_fd;

// ...
// ...
// ...
// ...
};
  • fork 구현시 유의 사항
    • child process를 만들고 현재 process의 context를 복사 한다.
      • 복사할때 interrupt frame의 값을 복사하는데 부모 프로세스가 실행중일때 interrupt frame의 값이 항상 최신 값들을 갖고 있지는 않기 때문에 현재 cpu 의 레지스터 값을 부모 프로세스에 백업(or 갱신) 해놓는다
      • 자식 프로세서가 실행될때 처음으로 수행하는 함수인 __do_fork 함수내에서 복사를 진행 한다.
      • 부모는 fork로 생성된 자식이 부모 복제를 완료 했는지 확인 해야하기 때문에 sema 와 같이 동기화 처리를 고민 해야 한다. (value가 0으로 초기화된 semaphore)
      • 복사가 완료되면 do_iret 함수를 사용해 interrupt frame에 저장된 값들을 cpu 레지스터에 올린다. →
      • 즉, 부모가 실행하던 부분부터 이어서 실행하게 된다. → fork 함수의 return은 부모, 자식 두번 발생 한다. → 자식은 0을 return 하도록 만들고, 부모는 새롭게 생긴 자식의 pid를 return 하도록 만든다.
        • 자식의 경우 __do_fork 함수 내부에서 do_iret 함수로 cpu 복사한 값이 올라갈때 return value를 나타내는 rax 레지스터 값은 0으로 변경.(자식의 fork 함수 return을 0으로 만들기 위해서 )
    • thread_create가 실패하거나 복사를 실패 했을때에 대한 적절한 처리가 필요하다.
      • 일단 복사를 진행 하는 함수인 __do_fork 함수 내에서 복사가 실패하면
        • do_iret을 실행하지 않는다.
        • sema를 사용했다면 부모를 다시 ready list로 보내주기 위해서 sema_up을 해준다.
  • thread 가 init 될때 file descriptor table 에 대한 공간을 할당
    • 발생 할 수 있는 문제점
      • pintos는 기본적으로 메모리가 부족하지 않다면 process가 무한정으로 파일을 열 수 있어야 한다. → slack 질문 참조함
      • 따라서 미리 정의된 공간이 넘어서 file 포인터를 저장해야 하는 경우에 대해서 생각해봐야 한다.
        1. 새롭게 공간을 추가 할당해주고 저장을 하는 방식 → pintos의 요구사항에 좀 더 적합, 메모리가 허락하는한 file을 계속 open 할 수 있다.
        2. 미리 정의된(할당된) 공간을 초과해서 저장하려는 시도시에 file 을 저장하지 않고 close 해주는 방식 → 미리 정의된 사이지만 저장 할 수 있다.
      • 2번 방식으로 fdt를 구현 및 사용하면 사이즈를 초과해서 저장을 시도할때 적절히 처리해줘야한다.

0개의 댓글