Pintos 완주 후 다시 읽기
스레드, 프로세스, VM, 파일 시스템을 한 요청 흐름으로 묶어 Pintos 전체 지도를 만든다.
이 글에서 다루는 것
앞선 글들이 각각 interrupt, process, VM, file system을 따로 보았다면, 이번 글은 하나의 요청이 그 층들을 어떻게 지나가는지 본다. 완성 후 다시 읽기의 목적은 바로 이 전체 지도를 갖는 것이다.
- user program의 write 요청이 kernel로 들어오는 길
- user pointer 검증 중 VM이 개입하는 지점
- fd table에서 file 객체를 찾고 inode/FAT까지 내려가는 흐름
- 완주 후 코드를 다시 볼 때의 읽기 순서
1. 요청 하나를 끝까지 따라가면 구조가 보인다
예를 들어 user program이 write(fd, buffer, size)를 호출했다고 하자. 이 요청은 단순히 파일에 쓰는 함수 하나로 끝나지 않는다. syscall 경계, user memory 검증, fd table, file layer, inode, FAT가 순서대로 이어진다.
write 요청의 전체 지도
2. syscall handler는 요청을 커널 객체로 바꾼다
case SYS_WRITE: {
int fd = (int) f->R.rdi;
void *buffer = (void *) f->R.rsi;
unsigned size = (unsigned) f->R.rdx;
enum process_fd_type type;
struct file *file;
user_check_read (buffer, size);
type = process_get_fd_type (fd);
if (type == PROCESS_FD_FILE) {
file = process_get_file (fd);
lock_acquire (&filesys_lock);
f->R.rax = file_write (file, buffer, size);
lock_release (&filesys_lock);
}
break;
}
이 코드에서 중요한 줄은 user_check_read(buffer, size)와 process_get_fd_type(fd)다. user가 준 값은 그대로 믿을 수 없고, fd 숫자도 커널 내부 file 객체가 아니다. 커널은 이 둘을 검증하고 번역해야 한다.
user program이 들고 있는 작은 정수다. 그 자체로 파일을 가리키지 않는다.
fd table을 거쳐 얻는 실제 커널 객체다. file인지 directory인지에 따라 가능한 연산도 달라진다.
3. user pointer 검증은 VM과 떨어져 있지 않다
Project 2까지만 보면 user pointer 검증은 주소가 user 영역인지 확인하는 방어 코드처럼 보인다. 하지만 Project 3 이후에는 lazy page와 stack growth 가능성도 고려해야 한다. 즉 syscall은 VM 위에 얹혀 있다.
4. file layer는 위치를 관리하고, inode layer는 실제 저장을 처리한다
off_t
file_write (struct file *file, const void *buffer, off_t size) {
if (file_is_dir (file))
return -1;
off_t bytes_written = inode_write_at (file->inode, buffer, size, file->pos);
file->pos += bytes_written;
return bytes_written;
}
file_write()는 현재 file position을 기준으로 쓰고, 실제 바이트 쓰기는 inode_write_at()으로 넘긴다. 이 분리가 중요하다. fd로 열린 file 객체는 현재 위치를 기억하지만, 데이터가 디스크 어디에 저장되는지는 inode와 FAT가 담당한다.
층별 책임 정리
5. 완주 후 다시 읽는 순서
Pintos를 끝낸 뒤 한 번 더 훑는다면 처음부터 모든 파일을 다시 읽기보다, 대표 요청을 하나 잡고 아래 순서로 따라가는 편이 좋다.
검증 기준
이 시리즈는 실제 구현 코드의 함수 흐름을 확인해 작성했다. 마지막 파일 시스템 기준으로는 basic/extended 파일 시스템 테스트 146개 PASS 결과가 남아 있는 코드 상태를 근거로 삼았다. 글의 목적은 새 패치 가이드가 아니라, 완성한 사람이 다시 전체 구조를 설명할 수 있도록 만드는 재독 지도다.
이번 글에서 기억할 것
- Pintos 전체는 thread, process, VM, filesys가 따로 존재하는 것이 아니라 한 요청 안에서 이어진다.
- user 값은 syscall에서 검증되고, user memory는 VM에서 보장되며, file 요청은 inode/FAT까지 내려간다.
- 완주 후 복습은 기능별 암기보다 대표 흐름을 끝까지 따라가는 방식이 더 강하다.
스스로 점검
- write 요청에서 fd 숫자가 실제 file 객체로 바뀌는 지점은 어디인가?
- user buffer 검증 중 page fault가 발생할 수 있는 이유는 무엇인가?
- file 객체와 inode의 책임은 어떻게 다른가?
- 새 테스트가 실패했을 때 어느 층에서 멈췄는지 구분할 수 있는가?
한 줄 정리
Pintos를 완성한 뒤 다시 보면, 운영체제는 요청 하나를 안전하게 아래층까지 번역해 내려가는 여러 층의 약속이었다.