컴퓨터 시스템/OS

[WIL] 컴퓨터 운영체제 'USER PROGRAMS' (pintos week2) - 작성 중

Campkim 2021. 10. 14. 11:12

PINTOS week 2 수행과제

  • Pintos week2 수행 주제 - 'User program' 
  • 1주차까지 kernal thread만 다루었다. 이번 주차부터 user program 실행, 종료 및 주요 System call (system handler)등을 구현하며 시스템콜 작동 원리를 익힌다.
  • 구현 과제 - argument passing / syscall handler / syscall / user memory access / denying writes executables

  • WIL Key word 
    • Argument passing & x86-64 Calling Convention 
    • System call ( Syscall handler, Syscall, exception, register ) 
      • user mode, kernal mode
      • halt, exit, fork, exec, wait, create, remove, open, filesize, read, write, seek, tell, close, dup2
    • User memory access & Denying writes executables

Argument passing - 프로세스 로딩 & 실행

생성된 kernal thread 에서 process를 실행시키는 'process exec' 함수는 구현되어 있다. 하지만 몇 가지 문제가 남아있었다. 

  • command line을 통해 전달되는 명령어가 실행파일, 인자값으로 parsing되어 전달되지 않았다.   
  • parsing 후 실행파일 load 및 return address & argument 가 'x86-64 Calling Convention'에 맞추어 전달되어야 한다. 

예를들어 실행에 필요한 인자값이 2개인 프로세스가 로드되고 실행될때 'filename argument1 argument2'와 같은 형태로 명령어에 입력된다. 명령어들이 적재적소에 들어가게 만들어야 한다. command line parsing은 하기 함수의 도움을 받았다. 

 

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

설명

더보기

string을 delimeter 기준으로 쪼개서 하나씩 return한다. return된 문자들을 token이라고 부르는데, **save_ptr에는 반납된 token 다음 토큰의 메모리 주소를 가리키는 값이 저장된다.  

	int argc = 0 ;
	char * save_ptr, *token;
	char * argv[128];
	void *rsp;

	token = strtok_r(file_name, " ", &save_ptr);
	while (token != NULL)
	{
		argv[argc] = token;
		token = strtok_r(NULL, " ", &save_ptr);
		argc++;
	}

 

parsing 완료 후 실행에 필요한 인자값들을 필요에 맞게 stack에 쌓아야한다. PINTOS 에서는 x86-64 Calling 'Convention'에 맞추어 삽입한다. Convention이기 때문에 다른 운영체제 혹은 아키텍쳐에서 적용되는 다른 convention도 있을 수 있겠다고 생각했지만 알아보진 않았다. 암튼 convention이기 때문에 왜 이렇게 쌓냐는 의문은 넣어두고 그냥 규범에 맞추어 넣으면 된다. 초기화된 스택영역은 0x47480000 에서 시작했다. 하기와 같이 넣어주면 놀랍게도 실행된다. 규범을 어기면 실행이 안된다.

 

하기와 같은 순서로 쌓아주면 된다. USERSTACK으로 정의된 0x47480000 부터 argument / address / return address

pintos stack 요구사항
새로운 프로그램 시작시, 전형적인 user stack

System call -  Syscall handler, Syscall, exception, register

다른 프로세스, 혹은 커널에 악의적인 영향을 주지 않도록, 하나의 유저 프로그램 혹은 프로세스는 다른 실행영역에서 Isolation 되어있다. 유저모드에서 수행가능한 기능들은 제한되어 있으며 권한을 넘어선 기능은 커널모드에서 실행된다.  그럼에도 악의적인 접근으로 판단될 수 있는 작업을 하게되면 프로세스는 강제적으로 종료된다.

 

User mode와 kernel mode의 권한 구분은 Ring 0 ~ Ring 3와 같이 구분되어 있다. 유저모드에서 커널모드로 trap되면 권한도 3 -> 0으로 격상된다. 

권한 구분 

 

 

System call이란 User program이 OS의 지원(커널모드에서의 기능)이 필요한 기능들을 사용하기 위한 방법이다. 커널모드로 trap전에 해당 syscall에 들어온 인자값들이 유효한 주소에 해당하는지, 시스템에 치명적인 변경점을 시도하지 않는지 등 확인한다.

 

system call함수는 겉보기에는 일반 함수들과 비슷한 모양을 가지고 있다. 유저모드에서 시스템콜이 실행되면 인자로 입력된 값들을 레지스터에 넣고 syscall을 실행한다. 해당 함수에서 context가 저장되고 syscall handler로 제어권이 넘어간다. 이어서잓ㅇ

 

 

 

 

도움된 자료

https://scslab-intern.gitbooks.io/linux-kernel-hacking/content/chapter05.html

 

5. System calls · Linux kernel hacking

 

scslab-intern.gitbooks.io