/////
Search

Pre

How User Program Work

실제 파일 시스템에 올라와있는 파일들을 핀토스에서 직접 불러서 실행시키고, Host OS가 쓰는 구조인듯?
1.
파일 시스템 디스크를 생성
cd ~/pintos/src/userprog make cd build pintos-mkdisk filesys.dsk --filesys-size=2 // pintos-mkdisk: 핀토스에서 제공하는 가상 디스크 생성도구. // 디스크 이름은 무조건 filesys.dsk로 해야함. // --filesys-sizze=2 : 가상 디스크 용량을 2MB
JavaScript
복사
2.
파일 시스템 디스크 초기화
cd ~/pintos/src/examples make cd ../userprog/build pintos -f -q // filesys.dsk를 포맷. 핀토스의 자체 파일 시스템 구조 사용 // 모든 작업이 끝나면 핀토스를 종료. 없으면 화면이 멈춤
JavaScript
복사
3.
파일 시스템 디스크에 실행할 응용 프로그램 복사(echo 프로그램 복사)
pintos -p ../../examples/echo -a echo -- -q // -p : echo 실행파일을 생성된 핀토스 디스크 파티션으로 복사 // -a : 프로그램 이름을 echo로 설정 // -- : boche 옵션과 핀토스 옵션을 구분, 왼쪽은 boche, 오른쪽은 핀토스 // 실행 프로그램은 Regular ELF 형식
JavaScript
복사
4.
프로그램 실행(echo 프로그램을 x라는 인자를 넣어서 실행(
pintos -q run 'echo x' // run : 응용 프로그램을 실행 // 주: 핀토스의 현재 상태로는 응용 프로그램 실행 불가
JavaScript
복사
5.
결합된 명령어
pintos —filesys-size=2 -p ../../examples/echo -a echo — -f -q run ‘echo x’ // 옵션은 반드시 -p, -a, --, -f, -q, -run 순서
JavaScript
복사

프로그램의 실행

run 옵션일 경우 run_task() 호출
호출하면 그 다음 어쩌라고
최종 목표
왜 안되냐?

전체적인 함수 실행 순서

여기서 좀 중요한 함수 → start_process
start_process
프로세스를 위한 메모리 공간 확보
실행파일을 메모리에 탑재
프로그램 시작: 스택 프레임 설정, 프로그램 카운터 변경

start_process에 대한 함수 호출

전체적인 흐름

프로세스 생성

thread_create()
file_name : 스레드 이름(문자열)
PRI_DEFAULT : 스레드 우선순위
start_process: 생성된 스레드가 실행할 함수를 가리키는 포인터
fn_copy: start_process 함수를 수행할 때 사용하는 인자 값.
tid_t process_execute(const char *file_name) { char *fn_copy tid_t tid; ... tid = thread_create(file_name, PRI_DEFAULT, start_proecess, fn_copy); ... return tid; }
JavaScript
복사

스레드 생성

프로세스 디스크립터(struct thread) 생성 및 초기화
커널 스택 할당 후 커널 스레드가 수행할 함수를 등록
커널 스레드를 run queue(ready list)에 추가
tid_t thread_create(const char *name, int priority, thread_func *function, void *aux){ struct thread *t; struct kernel_thread_frame *kf ... t = palloc_get_page(PAL_ZERO); // 페이지 할당 init_thread(t,name,priority); // thread 구조체 초기화 tid = t->tid = allocate_tid(); // tid 할당 // stack frame for kernel_thread(); kf = alloc_fram(t,sizeof *kf); // 커널 스택 할당 kf->eip = NULL kf->function = function; // 스레드가 수행할 함수 kf->aux = aux; // 수행할 함수의 인자. ... /*Add to run queue.*/ thread_nblock(t); return tid; }
JavaScript
복사

프로세스 탑재

load(): file_name의 프로그램을 메모리에 탑재
메로리 탑재 성공 시 응용 프로그램 실행, 실패 시 스레드 종료
thread_exit();
static void start_process (void *file_name_) { char *file_name = file_name_; ... /* if_.espЕ ݛ 스택 포인터*/ success = load (file_name, &if_.eip, &if_.esp); if (!success) thread_exit (); /* start user program */ asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory"); }
JavaScript
복사

실행 파일의 메모리 탑재

ELF 파일 포맷에 따라 메모리 탑재
파일을 Open하고 ELf 파일의 헤더 정보를 저장
프로그램 배치 정보를 읽어 파일에 데이터를 메모리에 탑재
스택 생성 및 초기화
bool load(const char *file_name, void (**eip) (void), void **esp){ struct thread *t = thread_current(); struct Elf32_Ehdr ehdr; struct fil *file = NULL; t->pagedir = pagedir_create(); // 페이지 디렉토리 설정 proces_Activate() // 페이지 테이블 활성화 file = filesys_open(file_name); /* ELF 파일의 헤더 정보를 읽어와 저장 */ if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) || ehdr.e_type != 2 || ehdr.e_machine != 3 || ehdr.e_version != 1 || ehdr.e_phentsize != sizeof (struct Elf32_Phdr) || ehdr.e_phnum > 1024) /* 배치 정보를 읽어와 저장*/ struct Elf32_Phdr phdr; 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 (esp)) /* 스택 초기화 */ ... }
JavaScript
복사