[Pintos] project 2 -WIL

DoHee·2023년 5월 8일

SW정글_6기

목록 보기
5/7

Argument Passing

  • process_exec() : 커맨드 라인 명령을 수행할 수 있도록 메모리에 적재하고 실행하는 함수. f_name에 저장된 문자열을 공백 기준으로 parsing하도록 코드 추가

인자 파싱할 때 주의점

  1. 문자열을 파싱할 때, 다른 함수에서 원본 문자열을 쓸 수 있으므로 따로 복사본을 만들어서 사용해야 함.
  2. 문자열의 끝에는 문자열이 끝났다는 것을 의미하는 '\n'이 들어가며, 이것을 센티넬(sentinel)이라고 함. 복사하거나 자를 때 센티넬까지 고려해야 함.

인터럽트 프레임(Interrupt Frame)

인터럽트가 발생했을 때, 이전에 레지스터에서 작업하던 컨텍스트를 switching 하기 위해 기존 정보를 담아 놓는 역할의 구조체.
실행 중인 프로세스와 레지스터 정보, 스택 포인터, instruction count를 저장하는 자료구조로, 커널스택에 있음

  • rsp : 스택 포인터
  • rax : 리턴 값, temp register
  • rdi, rsi, rdx : 차례로 함수의 1, 2, 3번째 인자를 저장

strtok_r(char s, const char delimiters, char **save_ptr)

S는 분리하고자 하는 문자열, delimiters는 문자열을 구분하는 기준(구분자), save_ptr는 문자열이 차례로 분리되면서 남은 문자열을 가리키는 포인터.

argument stack()

파싱한 인자를 스택에 올려주는 역할. argument_stack 함수에서 인터럽트 구조체 안의 rsp에 인자를 넣어주면, do_iret 함수에서 이 인트럽트 프레임을 스택에 최종적으로 올려준다.

  1. 파싱한 각 인자를 역순으로 유저 스택에 넣어줌. 각 인자에서 인자의 크기를 읽어서 그 크기만큼 if_->rsp (현재 위치를 가리키는 스택 포인터)를 내려주고, 그 공간에 memcpy로 인자를 복사해 넣어줌.
  2. word-align을 맞춰 줌. 8의 배수를 맞춰줘야 하므로 if_->rsp를 하나씩 내리면서 8의 배수가 아닌 주소에 0을 삽입함. (padding 삽입)
  3. 각 인자를 저장한 주소를 삽입해 줌(센티넬 포함) rsp를 8바이트씩 내리면서 주소값을 넣어줌.
  4. fake address를 넣어 주고, 0으로 초기화 해줌.
  5. 인터럽트 프레임(if_)의 레지스터값을 설정해줌. rdi에 인자의 카운트 값을, rsi는 fake address 바로 위 값을 가리키는 주소값을 넣어줌.

User Memory Access

  • 시스템콜을 구현하기 전, 커널이 유저의 가상주소공간에 접근할 수 있는 방법을 제시해줘야 함.
  • 포인터가 커널을 가리키거나 할당되지 않은 메모리를 가리키는지 체크해야 함.

Paging

물리메모리과 가상메모리를 일정 크기로 쪼갠 후, 그 크기에 맞춰 프로세스를 끼워넣는 방식.
가상메모리를 쪼개서 여러 Page로 만들고, 물리메모리도 Page와 같은 크기로 쪼개서 Frame으로 만든다.
그 후, 특정 Page와 Frame을 매핑한 페이지 테이블(Page Table)을 만듦. (페이징 기법을 이용하면 가상 주소와 물리 주소를 맵핑하는 페이지 테이블이 반드시 필요.)

Page Table

가상 주소 공간의 각 Page에 대한 물리 메모리 위치를 기록하기 위해, 운영체제는 각 프로세스마다 페이지 테이블이라는 자료구조를 제공함. 페이지 테이블은 주소공간의 가상 페이지 주소 변환(address translation) 정보를 저장하며, 이를 통해 가상 주소를 물리 주소로 변환이 가능함.
페이지 테이블은 실행 중인 프로세스 수가 많은 수록 매우 커질 수 있기 때문에 메모리에 저장됨.

System Calls

  • 운영체제가 제공하는 서비스에 대한 프로그래밍 인터페이스
  • 커널 모드에서 실행되고 처리후에 사용자 모드로 복귀함

시스템콜 처리 과정(Write)

유저 어플리케이션에서 무언가 작성할 때, 모니터에 출력하거나 작성한 내용을 저장하는 것 모두 커널(운영체제)의 도움이 필요함.

  1. 유저 프로그램 실행. 유저 프로그램에서 시스템 콜 write()를 호출함.
  2. write 함수는 인자를 유저 스택에 넣은 뒤, 커널로 진입. 이 때 스택 포인터(rsp)는 인자가 저장된 영역을 가리키고 있음.
  3. 커널의 인터럽트 벡터 테이블에는 어떤 종류의 인터럽트를 실행해야 하는지가 매핑되어 있는 자료구조. 이 중에서 시스템 콜 핸들러가 호출됨(0x30)
  4. 시스템 콜 핸들러가 제어권을 얻으면, 시스템 콜 넘버는 %rax에, 시스콜을 호출한 caller의 레지스터는 전달받은 인터럽트 프레임(커널스택에 있음) 안에 있음.

시스템 콜 핸들러 구현

  • 유저스택 포인터(rsp)와 인자가 가리키는 주소가 유저 영역인지 확인해야 함.
  • 시스템콜 함수의 리턴 값은 인터럽트 프레임의 rax에 저장.

halt()

핀토스를 종료시키는 시스템 콜 함수. Power_off 함수를 이용해 구현함.

exit()

stack 구조 이해

프로시저, 제어의 이동
call 과 ret 기능의 예제
call 인스트럭션은 함수의 시작 부분으로 제어를 이동, ret 인스트럭션은 call 다음에 오는 인스트럭션으로 제어를 되돌림

profile
정글_6기_b반

0개의 댓글