핀토스 운영체제에서 유저프로세스가 어떻게 실행되는지에 대한 구체적인 흐름을 꼭 잡고 가고싶어서 기록해본다.
언제나 시작은 init.c 로 부터. main() 함수 내에서 모든 부팅 과정을 마치면 run_actions (argv);
로 함수를 호출한다. argv는 입력한 명령어가 공백을 기준으로 분리된 배열이다.
i.e. 만약 명령어가 run alarm-single 이었으면, argv[0] = run, argv[1] = alarm-single, argv[2]= NULL 인 상태
actions 배열을 순회하면서 명령어의 첫번째 단어와 매칭되는 함수를 찾아서 실행한다.
유저 프로그램의 경우 run
명령어로 실행하므로 run과 매칭되는 함수인 run_task
를 실행한다. 아래의 코드가 run_task(argv)
를 호출하는 부분.
/* Invoke action and advance. */
a->function (argv);
run_task는 명령어에서 실행해야 할 task를 parsing 한다. argv에서 argv[0]은 run, ls 등 실행해야 할 명령의 종류가 담겨있다면 argv[1] 에는 어떤 파일을 실행해야 하는지에 대한 정보가 담겨있다. 이 부분을 task로 분리한다.
const char *task = argv[1];
이후 task 로 테스트를 실행하거나, 유저프로그램을 실행한다. 유저 프로그램이 실행되는 경우 아래의 코드를 통해 실행되는데, 이 흐름을 따라 가보자.
process_wait (process_create_initd (task));
이 함수가 인자로 받는 task는 ‘실행해야 할 파일 이름’ 일 수도 있지만 ‘실행해야 할 파일 이름+ 전달될 인자들’ 일 수도 있다. 따라서 첫 공백을 기준으로 실행해야 할 파일이름을 파싱하여, 이 이름으로 스레드를 생성한다.
이 스레드는 생성된 후 readylist 로 갈 것이고, 이 스레드가 실행될 때 initd(fn_copy);
를 실행할 것이다.
tid_t
process_create_initd (const char *file_name) {
char *fn_copy;
char *save_ptr;
char *not_used;
tid_t tid;
fn_copy = palloc_get_page (0);
if (fn_copy == NULL)
return TID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);
file_name = strtok_r(file_name," ",¬_used);
tid = thread_create (file_name, PRI_DEFAULT, initd, fn_copy);
if (tid == TID_ERROR)
palloc_free_page (fn_copy);
return tid;
}