Q . user process stack은 어디에서 초기화 되는가?
process_exec 를하면서 load(적재)할때 유저 프로세스의 페이지 테이블 생성
참고 : rsp USER_STACK으로 초기화 된다.
어디서 초기화 되는가? -> thread_create에서 palloc후 init_thread에서 rsp에 값을 집어 넣어주는것으로 확인됨
아래 그림은 레지스터와 interrupt frame 구조체, 레지스터의 쓰임을 보여준다.
UNIX의 File Descriptor
🤔 궁금증 : Process Descriptor Table이란?
출처 : https://subscription.packtpub.com/book/application_development/9781785883057/1/ch01lvl1sec9/process-descriptors
File Descriptor 테이블 추가
스레드 생성 시 File Descriptor를 초기화 하도록 수정
tid_t thread_create(const char *name, int priority, thread_func *function, void *aux)
프로세스 종료 시 열린 파일을 모두 닫도록 수정
void process_exit(void)
File Descriptor 사용을 위한 함수 추가
int process_add_file(struct file *f)
struct file *process_get_file(int fd)
int process_add_file(struct file *f)
File Descriptor 테이블 추가
여기서 struct thread* curr = thread_current();
라고 했다면 현재 돌고있는 스레드의 주소를 가리키는게 curr일텐데 만약에
인터럽트를 당해서 현대 쓰레드가 다른 주소로 옮겨졋다면?
문제가 발생한다.
만약 여기서 struct thread* curr이라고해놓고 밑에서 값들을 다바꿔둔뒤
process_add_file이 종료된다면? 그 안에 있는 값들은 다바뀌지만
그 주소는 날라간다.
그래서 항상 thread_current를 정적으로 선언해줄때 이게 data를 공유하는지 아닌지를 계속 생각해서 정적으로 박아두고 쓸지 아니면 thread_current 본연의 그 날것 그 자체를 갖다 쓸것인지 고민해야됨
Q. 페이지 테이블이랑 페이지 디렉토리의 차이?
A. 페이지테이블 :물리메모리 주소를 ~ ? (컴퓨터 시스템의 9장을 읽자)
file_duplicate 함수
pos를 덮어써주는이유 : 부모가 읽은 위치에서 자식이 읽게해야 하니까.
함수 파라미터에 UNUSED를 굳이 써주는이유?
함수 파라미터로 어떤 값을 넘겨받고 그 함수안에서 그 파라미터를 쓰지 않을 경우 보통 컴파일러가 warning(경고) 메시지를 보내주는데 UNUSED를 통해서 경고 메시지를 보내주지 않는다.
핀토스 프로젝트 1에 이어 User program 프로젝트 2를 진행하면서 좀 더 운영체제의 입장에서 어떻게 유저 수준과 커널 수준이 나뉘어서 프로세스가 진행 되는지 이해할 수 있었다. 웹 서버 구현할 때도 궁금했던 것이 항상 main 문에서 argc와 **argv를 받아서 정보를 이용하는데, 이런 것들이 어떤 방식으로 받아와 지는지 궁금했었다. 결론적으로 운영체제는 명령어와 인자를 분리하여 그 정보를 이용하여 process를 생성, load하고 유저의 system call을 이용 한다는 사실을 알게 되었다.
user가 system call을 호출하면서 인자를 넘길때, 이 인자는 스택포인터를 통해 유저 스택에 정보가 저장되고 커널에서 어셈블리어를 통해 우리가 유저스택을 통해 저장해 놓은 interrupt frame을 따와서 레지스터에 넣어주는 과정을 이해할 수 있었다.
레지스터에 인자를 넘겨받으면서 system call interrupt handler를 호출하여 어떻게 system call function을 수행하는지 알 수 있었다.
각 system call function은 서로 유기적으로 연결되어 있으면서 특히 부모프로세스와 자식프로세스를 낳는 fork, 프로그램 실행을 위한 exec, 프로세스를 기다리는 wait 함수를 구현하면서 서로간의 confilct를 처리하면서 각 함수들의 동작을 이해할 수 있었다.
이러한 내용들을 이해하고 구현하면서 User program의 전반적인 프로세스를 이해할 수 있었다. 또한 구현을 위해 커널레벨과 유저레벨의 컨텍스트 스위칭 과정을 그림으로 그려보고 코드를 보며 이해하고 구현하면서 머릿속에 각인 시킬 수 있었다.