티스토리 뷰

운영체제

[PintOS] Project2-0 Background

bearn_soo 2024. 5. 22. 01:24

목표

유저모드에서 프로그램을 실행한다. 초기 PintOS는 유저 프로그램을 실행할 수 없다


PintOS 프로세스 실행과정

1. OS는 프로세스를 실행하기위해 인수를 받는다.

2. 인수를 받은다음 process_create_initd함수를 호출한다.

3. process_wait는 아무 작업을 하지않고 반환하고 있다.

초기 PintOS 프로세스 실행과정


PintOS 구현사항

init 프로세스의 id는 0이고 모든 프로세스의 부모프로세스가 된다.

현재 핀토스는 프로세스를 생성하고 스케쥴링한뒤 그냥 종료하고 있다.

  • init 프로세스 즉 운영체제가 종료하면  생성된 프로세스를 실행 시킬 수 없다
  • process_wait함수는 자식이 생성되고 완료될때까지 기다려야한다.

PintOS 최종목표


process_create_initd

process_create_initd함수는 file_name을 인자로 받아 파일 이름을 가져온다 ex) a.out, ls

thread_create를 호출해 새 스레드를 생성한다

  • 새 스레드가 생성되고 독립적으로 계속 실행된다
tid_t
process_create_initd (const char *file_name) {
	char *fn_copy;
	tid_t tid;

	/* Make a copy of FILE_NAME.
	 * Otherwise there's a race between the caller and load(). */
	fn_copy = palloc_get_page (0);
	if (fn_copy == NULL)
		return TID_ERROR;
	strlcpy (fn_copy, file_name, PGSIZE);

	/* Create a new thread to execute FILE_NAME. */
	tid = thread_create (file_name, PRI_DEFAULT, initd, fn_copy);
	if (tid == TID_ERROR)
		palloc_free_page (fn_copy);
	return tid;
}

thread_create

1. 실행할 함수의 이름, 우선순위 실행할 함수의 포인터 주소와 보조 매개변수를 입력한다

2. 커널 공간에 단일 페이지를 할당한다(4KB)

  • 4KB 단일 주소 공간을 초기화하여 thread strcut를 초기화

3. 쓰레드 ID할당

4. 커널 스택을 할당

  • 커널 스택에서 실행하려는 함수를 포함한 다양한 필드를 초기화한다.
  • 커널 스택에는 실행해야 할 함수의 주소가 포함되어 있다.

5. unblock함수로 쓰레드를 ready_list에 집어넣는다.


process_exec

1. 실행하려는 바이너리 파일의 이름을 인자로 받는다

2. 디스크에서 해당 바이너리 파일을 메모리로 로드한다 -> load()

  • 해당 바이너리 파일에서 실행할 명령어의 위치를 가져온다: _if->rip (function entry point)
  • 사용자 스택의 최상위 포인터를 가져온다: _if->rsp (user stack top)

3. 실패하면 -1을 리턴한다


load

  1. load함수가 호출되면 커널은 주어진 쓰레드에 대한 테이블을 생성한다.
  2. 파일을 open한다.
    • ELF 헤더를 읽는다.
    • ELF 헤더에는 이 파일이 어떻게 구성되어있는지에 대한 정보가 담겨있다.
  3. 파일 구문 분석한 다음 데이터 섹션을 데이터 세그먼트에 로드한다.
  4. 프로세스에 대한 스택을 생성한 다음 초기화를 진행한다.
    • struct thread에는 페이지 테이블에 대한 포인터가 포함되어있다 -> pml4
    • plm4에는 모든 데이터 구조에 대한 포인터가 포함되어있다.
      • datam, text, stack
  5. 스택의 진입점을 실행해야할 바이너리 변수의 진입점으로 초기화한다.
  6. load가 완료되면 운영체제는 메모리 안에 프로그램 파일의 스택을 초기화하고 데이터와 bss섹션을 초기화한 다음 텍스트 메모리를 초기화한다.
static bool load (const char *file_name, struct intr_frame *if_) {
	struct thread *t = thread_current ();
	struct ELF ehdr;
	struct file *file = NULL;
	off_t file_ofs;
	...
	/* 페이지 디렉토리를 할당하고 활성화합니다. */
	t->pml4 = pml4_create ();
	process_activate (thread_current ());
	/* 실행 파일을 엽니다. */
	file = filesys_open (file_name);
	...
	/* 실행 파일 헤더를 메모리로 읽고 검증합니다. */
	if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
			|| memcmp (ehdr.e_ident, "\177ELF\2\1\1", 7)
			|| ehdr.e_type != 2
			|| ehdr.e_machine != 0x3E // amd64
			|| ehdr.e_version != 1
			|| ehdr.e_phentsize != sizeof (struct Phdr)
			|| ehdr.e_phnum > 1024) {
		printf ("load: %s: error loading executable\n", file_name);
		goto done;
	}
	...
	if (file_ofs < 0 || file_ofs > file_length (file))
	file_seek (file, file_ofs);

	if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
	...
	if (!load_segment (file, file_page, (void *) mem_page, read_bytes, zero_bytes, writable))
	...
	/* 사용자 스택을 초기화 */
	if (!setup_stack (if_))
		goto done;

	/* 시작 주소 */
	if_->rip = ehdr.e_entry;
	...
}

 

메모리에 프로그램 파일이 로드된 상황


테스트 실행

기존 테스트를 제외한 77개의 테스트 FAIL

참고

https://www.youtube.com/watch?v=RbsE0EQ9_dY&list=PLmQBKYly8OsWiRYGn1wvjwAdbuNWOBJNf

 

GitHub - hyunS00/pintos-kaist: 크래프톤 정글 5기 Pint OS

크래프톤 정글 5기 Pint OS. Contribute to hyunS00/pintos-kaist development by creating an account on GitHub.

github.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함