ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Week 10 Learned
    WIL 2026. 5. 7. 14:41

    1. What

    이번 주는 "Pintos Threads 위에 User Program 실행 흐름을 올리기 시작한 주"였다.

    10주차의 큰 축은 세 가지였다. 첫째는 Pintos Project 2 - User Program 자체였다. Jungle/Week10/AGENTS.md를 보면 이번 단계의 핵심은 process_create_initd()/fork()/exec()로 이어지는 사용자 프로그램 실행, 시스템 콜 진입, 예외 처리, wait()/exit()를 통한 부모-자식 관계 정리까지 포함한 흐름을 다루는 것이다. 즉 이번 주부터는 단순 스레드 스케줄링이 아니라 "유저 코드가 커널 경계 안으로 들어왔을 때 어떤 검증과 자원 관리가 필요한가"를 본격적으로 다루기 시작했다.

    둘째는 구현 범위의 초점이 userprog/process.c, userprog/syscall.c, userprog/exception.c로 이동했다는 점이다. Jungle/Week10/fd-table-decision.md에는 현재 브랜치 작업 범위가 system call dispatcher, process argument passing, exit, write, 그리고 이후 파일 시스템 콜을 위한 준비 단계까지로 정리되어 있었다. 즉 이번 주는 Project 2 전체를 한 번에 끝내기보다, 시스템 콜 진입점과 프로세스별 자원 모델을 먼저 안정적으로 세우는 쪽에 가까웠다.

    셋째는 per-process fd table 설계를 팀 단위로 명시적으로 결정했다는 점이다. fd-table-decision.md와 fd-table-benchmark-result.md에는 0=stdin, 1=stdout, 2+=opened file 정책을 두고, 리스트/배열/하이브리드/해시 방식을 비교한 뒤 배열 기반 fd_table을 채택한 이유가 정리되어 있었다. 즉 이번 주는 기능 구현 주이기도 했지만, 이후 read/write/seek/tell/close가 공통으로 의존할 자원 모델을 고르는 설계 주이기도 했다.


    10주차의 카테고리는 User Program 실행 흐름 이해, 시스템 콜 진입 구조 정리, 파일 디스크립터 테이블 설계, DevContainer 기반 작업 규칙 유지였다.

    1. 가장 먼저 threads 이후 누적되는 userprog의 책임 범위를 다시 정리했다.
    2. 중간에는 process.c, syscall.c, exception.c를 중심으로 사용자 프로그램이 커널에 들어오는 경로를 읽었다.
    3. 후반에는 파일 시스템 콜 구현을 앞두고 fd table 구조를 비교하고, benchmark 근거까지 붙여 배열 방식을 선택했다.

    2. How

    1. 이번 주도 구현과 테스트는 모두 DevContainer 내부에서만 진행하고, source pintos/activate 이후 명령을 실행하는 규칙을 유지했다.
    2. 코드 읽기는 userprog/process.c와 userprog/syscall.c를 축으로 잡고, "사용자 프로그램 실행 -> 시스템 콜 진입 -> 자원 접근 -> 종료 처리" 흐름을 먼저 따라가는 방식으로 접근했다.
    3. 구현 범위는 한 번에 넓게 잡지 않고 argument passing, exit, write, 그리고 이후 파일 시스템 콜을 위한 fd table 준비 단계로 나누어 보았다.
    4. fd table은 감으로 고르지 않고, array/list/hybrid/hash 각각의 조회와 순회 비용을 비교한 로컬 benchmark 문서를 남겨 설계 이유를 명시했다.
    5. README와 AGENTS 문서를 통해 9주차부터 13주차까지 같은 DevContainer 환경을 사용한다는 점도 다시 확인하면서, 환경 차이보다 커널 구조 이해에 집중할 수 있게 정리했다.

    이번 주 방식은 "구현 기능 수 늘리기"보다 "유저 프로그램이 커널 경계 안으로 들어올 때 필요한 책임을 먼저 분리하고, 반복해서 쓰일 자료구조를 먼저 고정하는 방식"에 더 가까웠다.

    3. Approach

    이번 주 접근은 "스레드 내부 동작을 다루는 관점에서, 프로세스와 시스템 콜 경계를 설계하는 관점으로 전환하는 것"이었다.

    9주차가 ready_list, priority, donation, sleep list처럼 커널 내부 스케줄링 상태 변화에 집중했다면, 10주차는 사용자 프로그램이 커널에 무엇을 요청하고 커널이 어디까지 책임질지를 나누는 쪽으로 무게가 옮겨갔다. 그래서 이번 주에는 단순히 syscall.c에 분기문을 추가하는 식으로 보기보다, "유저 포인터 검증", "프로세스별 열린 파일 관리", "표준 입출력과 일반 파일을 같은 API 안에서 어떻게 구분할지"를 먼저 모델링하는 편이 더 중요했다.

    fd table 설계도 같은 맥락이었다. open()이 반환한 fd를 이후 read/write/seek/tell/close/filesize가 공통으로 참조해야 하므로, 이 문제는 단순 저장소 선택이 아니라 User Program 전체의 호출 규약을 정하는 일에 가까웠다. 배열 방식은 fd_table[fd]로 곧바로 조회할 수 있어서 hot path에 유리했고, Project 2 범위에서는 구현 복잡도와 유지 비용까지 고려했을 때 가장 현실적인 선택으로 정리됐다.

    즉 이번 주의 접근은 "지금 필요한 시스템 콜만 임시로 붙이기"보다 "이후 시스템 콜들이 공통으로 올라탈 수 있는 진입 구조와 자원 테이블을 먼저 정리하는 것"이었다.

    4. Learned

    User Program 단계부터는 "커널 내부 로직"보다 "경계 관리"가 훨씬 중요해진다

    스레드 프로젝트에서는 커널 내부 상태 전환이 핵심이었다면, 이번 주부터는 사용자 코드가 커널에 들어오는 순간 어떤 검증과 보호가 필요한지가 더 크게 보였다. 같은 기능 구현이라도 syscall dispatcher는 결국 "외부 입력을 어디서 받고 어디서 거절할지"를 정하는 문제라는 점이 분명해졌다.

    시스템 콜은 개별 함수보다 공통 진입 구조가 먼저다

    exit, write 같은 기본 시스템 콜을 먼저 다루더라도, 그 전에 dispatcher 구조와 인자 전달, 에러 처리 규칙이 정리되지 않으면 구현이 쉽게 산만해진다. 이번 주 자료에서 현재 범위를 dispatcher, argument passing, 기본 syscall, file syscall 준비로 나눈 이유도 이 흐름을 먼저 고정하기 위해서였다.

    fd table은 자료구조 선택이 아니라 호출 규약 설계다

    처음에는 리스트냐 배열이냐 정도의 선택처럼 보이지만, 실제로는 0, 1, 2+를 어떻게 해석할지, 닫힌 fd나 범위 밖 fd에서 무엇을 반환할지, read/write/seek/tell/close가 어떤 방식으로 공통 lookup을 쓸지를 같이 정해야 했다. 즉 fd table은 구현 세부사항이 아니라 User Program 계층의 공용 인터페이스였다.

    benchmark는 "성능 자랑"보다 설계 선택을 팀이 공유하는 장치였다

    fd-table-benchmark-result.md의 수치는 절대 성능 측정보다 상대 비교 지표에 가까웠지만, 적어도 왜 배열을 골랐는지 설명 가능한 근거를 남긴다는 점에서 의미가 컸다. 특히 Pintos Project 2에서는 read/write/seek/tell의 반복 lookup이 많다는 전제를 팀 전체가 같은 문장으로 공유할 수 있게 됐다.

    9주차의 품질이 10주차의 안정성에 직접 이어진다

    AGENTS 문서에도 적혀 있듯이 Pintos 프로젝트는 누적형이다. 결국 threads 단계에서 스케줄링과 동기화가 어설프면, 이후 userprog에서 보이는 문제를 순수하게 시스템 콜 문제로만 보기 어려워진다. 이번 주는 "이전 주차 코드를 발판으로 다음 계층을 올린다"는 누적형 프로젝트의 성격을 더 강하게 체감한 주였다.

    5. Keep

    • DevContainer 전용 작업 규칙과 source pintos/activate 습관은 이후 주차에서도 그대로 유지할 가치가 있다.
    • 기능 구현 전에 실행 흐름과 호출 경계를 먼저 정리하는 방식은 vm, filesys 단계에서도 계속 유효할 것 같다.
    • 설계 선택을 말로만 두지 않고 decision.md와 benchmark 문서로 남긴 흐름은 계속 가져가고 싶다.
    • 표준 입출력과 일반 파일처럼 "같은 API 안의 예외 케이스"를 먼저 정리하는 방식은 시스템 콜 구현에서 특히 도움이 된다.
    • 누적형 프로젝트라는 전제를 계속 의식하면서, 이전 주차 코드 품질을 다음 주차의 기반으로 보는 관점은 유지해야 한다.

    6. Problem

    • 이번 주 문서만 보면 exit, write, argument passing이 실제로 어느 수준까지 구현되었는지 한눈에 드러나는 진행 기록은 아직 부족하다.
    • fd table 설계 근거는 잘 남아 있지만, fork/exec/wait/exit 사이의 부모-자식 관계 정리나 종료 상태 전달 방식은 같은 밀도로 문서화되어 있지 않다.
    • 시스템 콜 단계에서는 포인터 검증과 예외 처리 전략이 중요한데, 현재 남아 있는 문서는 자료구조 결정 쪽에 비해 경계 검증 규칙을 충분히 드러내지 못한다.
    • README는 환경 구축 설명에 강점이 있지만, 현재 Project 2에서 통과한 테스트와 남은 테스트를 바로 보여 주는 운영 문서 역할까지 하지는 못한다.
    • Week9에서 했던 발표형 정리는 아직 userprog 단계 내용까지 촘촘하게 이어지지 않아, 구현 설명과 문서화 밀도에 차이가 있다.

    7. Try

    • 다음에는 syscall number, 인자 개수, 검증 포인트, 실패 시 처리를 표로 정리해 시스템 콜 규약을 먼저 고정한다.
    • fork/exec/wait/exit는 함수 단위 설명보다 부모-자식 상태 전이 그림으로 정리해 두는 편이 좋다.
    • fd table처럼 핵심 자원 구조는 자료구조 선택뿐 아니라 생성/open/close/exit 시점 책임까지 한 페이지에 함께 정리한다.
    • README나 별도 진행 문서에 통과 테스트, 남은 테스트, 현재 불안정한 영역을 체크리스트로 남긴다.
    • User Program 단계부터는 포인터 검증과 예외 처리 규칙을 별도 문서로 빼서, 기능 추가 때마다 기준이 흔들리지 않게 한다.

    8. Make Up For

    이번 주에 가장 먼저 메꿔야 하는 부분은 "User Program 구현 상태를 시스템 콜 단위로 검증 가능한 문서로 남기는 것"이다.

    • exit, write, open, read, close 등 주요 시스템 콜별 현재 구현 상태와 통과 테스트를 표로 정리해야 한다.
    • process_create_initd()/fork()/exec()/wait()/exit() 흐름을 부모-자식 관계 중심으로 짧게 문서화해야 한다.
    • fd table은 배열 선택 이유뿐 아니라 fd 할당, invalid fd 처리, close 후 정리, exit 시 전체 정리 정책까지 함께 고정해야 한다.
    • 포인터 검증과 예외 처리 규칙은 파일 시스템 콜이 늘어나기 전에 먼저 기준을 정리해 두는 편이 좋다.
    • 다음 주에는 기능을 늘리기 전에 "현재 syscall 계층의 공통 규약이 무엇인지"를 먼저 문장으로 고정해서, 구현이 케이스별 예외 처리로 흩어지지 않게 해야 한다.

    이번 주가 "Pintos Threads 위에 User Program 경계를 세우기 시작한 주"였다면, 다음 단계는 이 경계를 테스트와 문서로 더 단단하게 고정하면서 fork/exec/wait와 파일 시스템 콜 전반으로 확장하는 쪽이어야 한다.

    'WIL' 카테고리의 다른 글

    Week 9 Learned  (1) 2026.05.01
    Week 8 Learned  (0) 2026.04.23
    Week 7 Learned  (1) 2026.04.16
    Week 6 Learned  (0) 2026.04.09
    Week 5 Learned  (0) 2026.04.02
Designed by Tistory.