운영체제 · Pintos · Project 2 · Week 10
Pintos Project 2 발표 회고: 핀토스 제국은 어떻게 신민을 통제했는가
정글 10주차 발표 자료를 바탕으로 Project 2를 하나의 제국 행정 시스템으로 다시 정리했다.
- Project 2 발표 자료를 하나의 제국 세계관과 행정 시스템으로 다시 읽기
- process, syscall, fd, fork/wait를 각각 신민·검문소·열람증·생산 공장으로 연결하기
- 85/95 통과라는 결과를 미완성 제국의 행정 지도로 정리하기
1. x86 우주, QEMU 행성, Pintos 제국
이번 발표에서 우리는 Pintos Project 2를 기능 목록으로 설명하지 않았다. 하나의 제국으로 설명했다. x86이라는 우주, QEMU라는 행성, 그 안에 세워진 Pintos 제국. 이 제국의 황제는 커널이고, 유저 프로그램은 황제가 허락한 영토 안에서만 움직이는 신민이다.
초기의 Pintos는 왕궁만 있는 나라였다. 모든 코드가 커널 안에서 움직였고, 모든 권한이 한 장소에 모여 있었다. 빠르고 단순했지만 위험했다. 왕궁 안에서 누군가 실수하면 제국 전체가 무너졌다.
2. 신민의 탄생: process는 생애 관리 체계다
Pintos에서 신민의 이름은 process다. 신민은 자연발생하지 않는다. `process_create_initd()`에서 첫 신분이 등록되고, `initd()`가 첫 실행 흐름을 맡는다. `process_exec()`는 기존 몸을 버리고 새 실행 파일로 갈아입는 절차다.
`load()`는 ELF를 검증하고 user memory에 올린다. `setup_stack()`과 `setup_args()`는 신민이 들고 갈 짐인 `argc`, `argv`를 user stack에 배치한다. 모든 준비가 끝나면 `do_iret()`가 신민을 왕궁 밖, 즉 user mode로 내려보낸다.
3. 왕궁 봉쇄: syscall은 검문소다
제국의 제1국법은 왕궁 봉쇄다. 유저 프로그램은 파일을 열고 싶어도, 글자를 출력하고 싶어도, 자기 생을 마감하고 싶어도 커널 원본에 직접 손을 댈 수 없다. 반드시 syscall이라는 검문소를 지나야 한다.
검문소는 신민을 믿지 않는다. 유저가 넘긴 포인터는 문서가 아니라 도시락폭탄일 수 있다. 주소가 유저 영역인지, 페이지 테이블에 실제로 매핑되어 있는지 확인하지 않으면 커널이 터진다.
| 구분 | 제국어 | Pintos 구현 |
|---|---|---|
| 요청 | 민원번호 | `f->R.rax`에 들어오는 syscall 번호 |
| 서류 | 검문소에 제출하는 인자 | `rdi`, `rsi`, `rdx` 등 syscall argument |
| 검열 | 국가보안법 | `is_crazy_user_address()`, `is_crazy_user_buffer()` |
| 처형 | 반란 진압 | `curtain_call(-1)`로 해당 process만 종료 |
4. 문서고 통제: fd는 열람증이다
제국의 문서고는 원본을 신민에게 넘기지 않는다. 신민은 `struct file *`를 들고 다니지 않는다. 대신 번호표를 받는다. 이것이 file descriptor, fd다.
fd 0은 stdin, fd 1은 stdout, 일반 파일은 fd 2부터 배정된다. `open()`은 파일을 열지만 원본 포인터를 유저에게 주지 않는다. `fd_table`에 저장하고, 유저에게는 번호만 돌려준다.
5. 복제와 사망: fork는 인간 생산 공장이다
Pintos 제국의 신민은 자연발생하지 않는다. `fork`라는 산아 생산 제도로 노예를 찍어낸다. 하지만 단순 복사는 아니다. 노예는 주인의 기억과 집, 열람증을 이어받아야 하지만, 같은 공간을 공유하면 안 된다.
그래서 제국은 공유 대신 복제를 선택한다. `__do_fork()`는 부모의 register 문맥을 복사하되, 자식의 `rax`는 0으로 조작한다. 같은 사건인데 주인과 노예에게 서로 다른 진실을 배급하는 것이다.
거주지도 복제된다. `pml4_for_each()`가 주인의 영토를 순찰하고, `duplicate_pte()`가 user page만 새 페이지로 베껴준다. 노예는 주인의 집을 공유받는 게 아니라, 똑같이 생긴 독립 수용소를 지급받는다.
6. 85/95: 천년제국은 아직 미완성이다
최종 main 기준으로 전체 95개 테스트 중 85개를 통과했다. threads는 18개 모두 통과했고, userprog 기본은 64개 중 58개, filesys/base는 13개 중 9개를 통과했다.
남은 실패는 제국의 미완성 제도다. `rox-simple`, `rox-child`, `rox-multichild`는 실행 파일 금서 보호법, `lg/sm-random`과 `syn-remove`, `syn-write`는 문서고의 더 복잡한 처리, `multi-oom`은 자원 고갈 상황에서의 생존 정책과 연결된다.
Project 2는 syscall 몇 개를 만든 과제가 아니었다. 믿을 수 없는 신민에게 제한된 자유를 주기 위해, 검문소·열람증·생산 공장·사망신고소를 세우는 일이었다.