(6/1)
오늘은 create, remove, exec, wait을 주로 구현해보았다.
어제 fork 에서 너무 두들겨맞았더니, 오늘은 상대적으로 수월했다.
두 시스템 콜은 서로 반대되는 역할을 수행하게 된다. 아래의 노션 캡쳐본을 통해, 어떤 점이 다른지 확인해보자.
참고로 시스템 콜 종류가 많다보니, 작업을 마친 system call 에 대해선 이름 마지막에 完 자를 추가해주었다 🙂
create는 파일명이 file 인 파일을 생성해주는 시스템 콜이고,
remove는 파일명이 file 인 파일을 제거해주는 시스템 콜이다.
다만 create의 경우엔, 최초에 파일의 사이즈를 initial_size 로 설정해준다는 점만 다르다.
각각의 구현은 filesys.c 에서 찾은 filesys_create, filesys_remove를 활용하면 되기에 어렵지 않았다.
exec은 cmd_line 을 파싱해서, 거기에 인자로 주어진 executable로 문맥 전환을 해주는 시스템 콜이다.
특이한 점은, 깃북에는 parameter 문자열을 cmd_line 이라고 명명한 반면, 주어진 PintOS 소스코드 상에서는 file 이라고 명명했다는 점이다(처음부터 제공받은 lib/user/syscall.c 에 그렇게 적혀있음). 아마 싱크로가 덜 맞춰진 부분이지 않나 싶은데, 질문에 남겨봐야겠다.
내가 이해한 바로는, exec을 실행하면 process_exec을 부르고, process_exec 안에서 load를 부르고, load 안에서 argument 파싱 및 패싱을 진행한다. 그리고, 파싱된 0번째 인덱스에 해당하는 것이 executable filename 이다. exec은 결국 그 파일을 실행해주고 문맥 전환을 해주는 것이다.
wait은 pid 를 갖는 자식 프로세스의 실행이 종료되기를 기다리도록 하는 시스템 콜이다.
wait 함수는 이미 존재하는 process_wait 함수에 pid를 전달해주도록 했다. 물론 syscall_handler 함수 상에서 곧장 process_wait을 호출해도 되겠지만, 가독성과 일관성을 위해서 wait 함수도 별개로 선언해 사용해주었다 :)
부모 프로세스는, 자신의 child_list 필드를 순회하며 pid를 가지고 있는 자식 프로세스를 찾는다. 부모는 자식의 wait_sema에 대한 sema_down을 호출해서, 자식 프로세스가 실행하고 이후 종료하면서 wait_sema에 대한 sema_up을 해줄 때까지 '기다린다'.
혹시 이 '기다림'의 과정이 이해가 되지 않는다면, Project 1에서도 활용했던 synchronization primitives 중 하나인 세마포어를 조작하는 sema_down 함수를 다시 살펴보자. 위의 sema_down에서는, while문을 통해 sema-value == 0이 되기까지 계속 루프가 돌게된다. 즉, 해당 sema의 holder(여기선 자식 프로세스)가 모든 작업을 끝내고 종료하며 sema_up을 호출해 sema-value++을 해주길 기다리는 역할을 수행하는 것이다.
다시 process_wait으로 돌아와서, 자식이 exit함에 따라 부모가 호출한 sema_down의 while문이 끝나면, 결국엔 부모가 해당 wait_sema 를 획득하게 될 것이다.
부모는 이제 그 종료된 자식의 exit_status를 확인하고, child_list에 있는 해당 자식의 elem을 제거해주고, 좀 전에 확인해서 킵해놨던 자식의 exit_status 를 반환해준다.
위와 같이 file descriptor(fd)를 활용하는 시스템 콜도 open과 filesize는 구현해보았는데, 추후에 나머지 5개도 다 구현하는대로 한 번에 정리해보도록 하겠다!
내일도 열심히 해보자~