티스토리 뷰
목표
유저모드에서 프로그램을 실행한다. 초기 PintOS는 유저 프로그램을 실행할 수 없다
PintOS 프로세스 실행과정
1. OS는 프로세스를 실행하기위해 인수를 받는다.
2. 인수를 받은다음 process_create_initd함수를 호출한다.
3. process_wait는 아무 작업을 하지않고 반환하고 있다.
PintOS 구현사항
init 프로세스의 id는 0이고 모든 프로세스의 부모프로세스가 된다.
현재 핀토스는 프로세스를 생성하고 스케쥴링한뒤 그냥 종료하고 있다.
- init 프로세스 즉 운영체제가 종료하면 생성된 프로세스를 실행 시킬 수 없다
- process_wait함수는 자식이 생성되고 완료될때까지 기다려야한다.
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
- load함수가 호출되면 커널은 주어진 쓰레드에 대한 테이블을 생성한다.
- 파일을 open한다.
- ELF 헤더를 읽는다.
- ELF 헤더에는 이 파일이 어떻게 구성되어있는지에 대한 정보가 담겨있다.
- 파일 구문 분석한 다음 데이터 섹션을 데이터 세그먼트에 로드한다.
- 프로세스에 대한 스택을 생성한 다음 초기화를 진행한다.
- struct thread에는 페이지 테이블에 대한 포인터가 포함되어있다 -> pml4
- plm4에는 모든 데이터 구조에 대한 포인터가 포함되어있다.
- datam, text, stack
- 스택의 진입점을 실행해야할 바이너리 변수의 진입점으로 초기화한다.
- 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;
...
}
테스트 실행
참고
https://www.youtube.com/watch?v=RbsE0EQ9_dY&list=PLmQBKYly8OsWiRYGn1wvjwAdbuNWOBJNf
'운영체제' 카테고리의 다른 글
[PintOS] Project2-2 User Memory Access (0) | 2024.05.26 |
---|---|
[PintOS] Project2-1 Passing the arguments and creating a thread (2) | 2024.05.22 |
[PintOS] Project1-2 Alarm Clock (1) | 2024.05.20 |
[PintOS] Project1-1 Thread (1) | 2024.05.20 |
[PintOS] Project1-0 핀토스 시작과 설정 (5) | 2024.05.20 |