
이번 주 목표
이번 주의 핵심은 "운영체제의 심장부, 스레드를 직접 만들어보기"이다.
구체적으로는 세 가지 큰 줄기를 따라가야 한다.
첫째, 커널 수준의 스레드를 직접 생성하고 스케줄링하는 흐름을 이해한다. 운영체제가 어떤 스레드를 언제 실행할지 결정하는 그 원리를 코드로 구현한다.
둘째, 여러 스레드가 동시에 돌아갈 때 발생하는 race condition 문제를 직접 겪어보고, 이를 해결하는 동기화 도구들(semaphore, lock, condition variable)을 체득한다. "왜 이게 필요한지"를 느끼는 것이 목표이다.
셋째, 팀과 함께 하나의 코드베이스를 만들어 가는 협업 흐름을 익힌다. 개인 branch에서 작업하고 PR을 통해 master에 합치는 Git 협업 방식도 이번 주부터 본격적으로 시작된다.
어디까지, 어떻게 시도했는가?
🤝 우리 팀의 협업 방식
본격적인 구현 이야기 전에, 우리 팀이 어떻게 협업하였는지를 먼저 짚고 넘어가야 할 것 같다.
방식은 이랬다. 각자 순서대로 과제를 구현하고, 매일 저녁 9시에 코어타임을 통해 서로의 코드를 리뷰하였다. 단순히 코드를 보여주는 게 아니라 "나는 왜 이렇게 짰는지"를 설명하고, 어떤 코드를 main 브랜치에 merge할지 팀 전체가 토론해서 결정했다. 결정이 나면 그날 저녁 merge를 하고, 각자 다음날 pull 받아 다음 과제를 이어가는 흐름이었다.
🕰️ Alarm Clock
가장 먼저 건드린 부분은 Alarm Clock이었다. 원래 PintOS의 timer_sleep()은 busy-wait 방식으로 구현되어 있다. 쉽게 말하여, 타이머가 만료될 때까지 CPU를 잡고 놓지 않는 구조다. 이걸 sleep/wakeup 방식으로 바꾸는 것이 첫 번째 과제였다.
스레드가 잠들어야 할 시점을 기록하고, 타이머 인터럽트가 발생할 때마다 깨울 스레드가 있는지 확인하는 흐름을 만들었다. 머릿속으로 그림은 그려졌는데, 막상 코드로 옮기려니 생각보다 훨씬 막막했다. 결국 100%는 스스로 완성하진 못했고, 팀원의 코드를 main에 merge해서 다음 단계로 넘어갔다. 팀 협업의 의미이기도 하지만, 한편으로는 찜찜한이 남는 출발이었다.
🎯 Priority Scheduling
다음은 우선순위 스케줄링이었다. 스레드마다 우선순위(Priority)가 있고, 항상 가장 높은 우선순위의 스레드가 먼저 실행되어야 한다.
나는 일반적인 방식대로 하나의 리스트를 우선순위 기준으로 관리하는 구현을 했다. 그런데 팀 코어타임에서 한 팀원이 다른 방식을 들고 왔다. ready_queues[PRI_MAX+1] 형태의 배열, 즉 우선순위마다 별도의 큐를 두는 구조였다. 다른 팀과의 차별점을 만들어 보자는 취지로 적극적으로 밀었고, 코드도 가장 깔끔했다.
결국 코어타임 토론 끝에 그 팀원의 코드가 main에 merge되었다. 내 구현이 틀린 건 아니었지만, 더 명확한 코드 앞에서 자연스럽게 결론이 났다.
돌이켜보면 내가 테스트 케이스를 거의 신경 쓰지 않고 구현했다는 것도 한몫했다. 일단 동작하면 된다는 생각으로 달렸는데, 정작 "어떤 상황에서 맞게 동작해야 하는지"를 제대로 확인하지 않은 것이다. 이때부터 테스트 케이스의 중요성을 몸으로 느끼게 되었다. 구현과 검증은 따로 가는게 아니라는걸.
🔄 Priority Donation
이 부분이 이번 주에서 가장 머리가 아팠던 곳이다.
이번 구현의 목표는 Priority Donation이었다. 구현에 들어가기 전에 먼저 "왜 이게 필요한가"를 이해해야 했는데, 그 배경이 바로 Priority Inversion 문제다.
Priority Inversion은 세 가지 상황이 겹칠 때 발생한다. 높은 우선순위 스레드가 낮은 우선순위 스레드를 기다리는 상황, 거기다 중간 우선순위 스레드가 끼어들어 먼저 실행되는 상황, 이 모든 게 lock 경쟁에서 비롯된다는 것. 결과적으로 우선순위가 높은 스레드가 가장 늦게 실행되는 역설이 생긴다.
이를 해결하기 위한 게 Priority Donation이다. 핵심은 두 가지다. 하나는 우선순위 양도 - lock을 요청하는 스레드가 더 높은 우선순위를 가지고 있으면, lock을 보유한 스레드에게 그 우선순위를 넘겨준다. 이때 여러 단계의 donation 체인이 생길 수 있다. 다른 하나는 우선순위 복원 - lock이 해제되면 원래 우선순위로 돌아온다. 여러 lock을 동시에 쥐고 있다면 그 중 가장 높은 donated 우선순위를 유지하다가, 모든 lock이 해제된 뒤에야 완전히 복원된다.
하루를 통째로 개념 학습에 썼다. 어느 정도 이해했다고 생각하고 구현에 들어갔는데 중간에 막혔다.마무리를 못 한 채로 코어타임에 들어갔고, 내 코드를 리뷰하면서도 스스로 길을 잃었다. 그래서 내가 이해한 개념을 팀원들에게 설명해봤는데 - 알고보니 처음부터 개념을 잘못 잡고 있었다.
다른 팀원들은 그 하루 동안 개념도 잡고 구현도 꽤 진도를 뺐는데, 나는 밤 11시가 넘어서야 개념을 다시 처음부터 공부해야 하는 상황이 됐다. 팀원들보다 하루가 그래도 밀린 셈이었다. 민폐가 되는 것 같아서 조급했고, 결국 donate-one과 donate-multiple 테스트 케이스만 통과한 채로 이번주를 마무리했다. 나머지 케이스들은 손을 대지 못했다.
🎤 목요일 발표
목요일에는 팀별 발표가 있었다. 내가 맡은 파트는 두 가지였다.
첫 번째는 Priority Donation 개념 설명이었다. Priority Inversion이 왜 생기는지, 그래서 Priority Donation이 왜 필요한지, 그리고 우선순위가 어떻게 양도되고 복원되는지를 설명했다. 직접 개념을 잘못 이해했다가 밤새 다시 잡은 경험이 있어서인지, "여기서 헷갈리기 쉬운 이유"를 꽤 자연스럽게 짚을 수 있었다. 실패가 설명의 재료가 된 셈이다.
두 번째는 프로젝트 회고 파트였다. 이번 주 팀이 어떻게 협업했는지를 정리해서 발표했다. test.c 함수를 직접 타고 들어가며 PintOS 내부 동작 원리를 학습한 것, 각자 구현 후 코어타임에서 코드를 비교하고 merge 방향을 논의한 것, 어려운 부분은 팀원들과 함께 해결해 나간 것. 그리고 미완성으로 끝난 부분에 대해서는 다음 주에 추가 시간을 투자해 완성도를 높이겠다는 계획도 함께 공유했다.
이번 주 아쉬웠던 점
이번 주 나의 방식은 항상 개념을 먼저 다지고 구현에 들어가는 것이었다. 그 방향 자체는 맞았다고 생각한다. 문제는 Priority Donation에서 개념을 잘못 잡은 채로 시간을 쏟아부었다는 점이다. 방향은 옳았는데 나침반이 틀렸던 셈이다.
가장 아쉬운 건 각 과제를 끝까지 내 손으로 마무리하지 못했다는 것이다. Alarm Clock도, Priority Scheduling도, Priority Donation도 - 어느 하나 완전히 내 힘으로 완성했다고 말하기 어렵다. 팀 협업의 구조 상 자연스러운 결과이기도 했지만, 그게 오히려 더 찜찜하게 남는다. "팀 코드가 통과됐다"는 것과 "내가 구현할 수 있다"는 건 다른 이야기니까.
그래서 개인 repo를 따로 파서, 각 과제를 처음부터 끝까지 혼자 완성해보고 싶다는 생각이 들었다. 테스트를 통과하는 것보다 "내가 왜 이렇게 짰는지" 스스로 설명할 수 있는 상태가 되는 게 목표다.
MLFQS까지 손을 못 댄 것도 아쉬움으로 남는다. 원래 계획에는 있었지만, Priority Donation에서 시간을 많이 소비했고 결국 다음 주로 미뤄졌다.
다음 주 계획
다음 주는 PROJECT 2 — User Programs로 넘어간다. 이번 주와는 결이 다른 주제들이 기다리고 있다.
핵심은 사용자 프로그램이 커널의 제어 아래 안전하게 실행되는 전체 흐름을 이해하고 구현하는 것이다. 구체적으로는 ELF 로더, 시스템 콜, 파일 디스크립터, 그리고 유저-커널 주소 검증까지. 이번 주가 스레드 내부 동작에 집중했다면, 다음 주는 사용자 프로그램이 커널을 어떻게 호출하고, 커널이 어떻게 그것을 안전하게 처리하는지를 다루는 셈이다. User Mode와 Kernel Mode가 나뉘는 이유, 그 경계에서 일어나는 일들을 직접 손으로 만들어 보게 된다.
이번 주에 다 못했거나 부족한 부분은 개인 repo를 따로 파서 틈틈이 마무리할 계획이다. 팀 코드가 넘어가더라도, 내 손으로 끝까지 짜본 적 없는 코드는 내 것이 아니라는 걸 이번 주에 분명히 느꼈다.
다음 주는 개념을 먼저 단단히 다지고 들어가는 방식을 더 철저하게 지키고 싶다. 이번 주에 방향은 맞았지만 나침반이 틀렸던 경험 덕분에, 개념을 검증하는 습관의 중요성을 배웠다. 팀원에게 설명해보는 것도, 스스로 말로 풀어보는 것도 — 이해를 확인하는 방법으로 적극적으로 활용할 생각이다.
9주차 팀원 블로그
Week 9 Learned
What9주차의 첫째는 Pintos Project 1 - Threads 자체였다. Jungle/Week9/README.md를 보면 이번 프로젝트의 목표는 Alarm Clock, Priority Scheduling, Priority Donation, MLFQS를 구현하고 테스트하는 것이었다. 둘째는 구현
minishell.tistory.com
WIL 9주차. Pintos Project 1을 시작하며 이해한 OS와 Thread의 기본 흐름
WIL 01. Pintos Project 1을 시작하며 이해한 OS와 Thread의 기본 흐름이번 주는 Pintos Project 1을 진행하면서 thread, scheduler, timer, synch가 어떤 관계로 움직이는지 이해하는 데 많은 시간을 썼다.처음에는 "프
app2.tistory.com
크래프톤 정글 9주차 WIL
WIL - Pintos Threads 학습 정리 이번 주에는 Pintos Project 1의 thread 관련 기능들을 순서대로 학습했다. 큰 흐름은 timer_sleep() 구현, Pintos list 구조 이해, priority scheduling, semaphore와 condition variable, priority dona
velog.io
'Krafton-Jungle > WIL' 카테고리의 다른 글
| Week 11. 정글 끝까지(PintOS) - Virtual Memory (0) | 2026.06.06 |
|---|---|
| Week 10. 정글 끝까지(PintOS) - User Programs (0) | 2026.05.21 |
| Week 8. 탐험 준비 (1) | 2026.04.23 |
| Week 7. 탐험 준비 (0) | 2026.04.16 |
| Week 6. 탐험 준비 (0) | 2026.04.09 |
