모던지 / 컴퓨터과학 / 컴퓨터의 원리 4강. 자원을 나눠 쓰는 기술

컴퓨터의 원리 4강. 자원을 나눠 쓰는 기술

여러분의 프로그램은 CPU를 독차지하고 있다고 믿습니다. 그 믿음을 유지시켜 주는 정교한 사기가 운영체제입니다.

풀고 시작

문제 1. 코어가 하나뿐인 컴퓨터에서 여러 프로그램이 동시에 돌아가는 것처럼 보이는 이유는 무엇일까요?
코어 하나가 한 순간에 밀고 나가는 실행 흐름은 기본적으로 하나입니다. 수십 개 프로그램이 함께 돌아가는 것처럼 보이는 이유는 운영체제가 수 밀리초 단위로 실행 주체를 바꿔치기하기 때문이죠. 메모리를 나눠 쓰는 것은 격리의 문제이지 동시성의 원인이 아니고, 저장 장치 배정은 별개의 이야기입니다.

운영체제는 무엇을 대신해 주는가

초창기 컴퓨터에는 운영체제가 없었습니다. 프로그래머가 예약표에 이름을 올리고 자기 차례가 되면 기계 앞에 앉아, 자기 프로그램뿐 아니라 프린터를 제어하는 코드까지 직접 짰습니다. 다음 사람이 오면 모든 것을 지우고 처음부터 다시 시작했죠. 기계는 사람이 카드를 갈아 끼우는 동안 계속 놀았고, 그 유휴 시간이 당시로서는 엄청난 낭비였습니다. 이 낭비를 줄이려는 시도가 작업을 모아 자동으로 이어 돌리는 일괄 처리로, 다시 여러 사용자가 한 기계를 번갈아 쓰는 시분할(time-sharing)로 진화했고, 그 계보 위에서 1969년 벨 연구소의 켄 톰슨과 데니스 리치가 유닉스를 만듭니다. 운영체제가 하는 일은 크게 둘로 정리됩니다. 하나는 추상화입니다. 제조사마다 다른 저장 장치의 물리적 특성을 감추고 "파일"이라는 하나의 개념으로 보여 주는 식이죠. 다른 하나는 자원 관리입니다. CPU 시간, 메모리, 입출력 장치를 누가 언제 얼마나 쓸지 중재합니다. 응용 프로그램이 하드웨어를 몰라도 되는 이유가 이 두 가지 덕분입니다.

프로세스와 스레드

실행 중인 프로그램을 프로세스(process)라고 부릅니다. 프로그램은 디스크에 얌전히 누워 있는 명령어 뭉치일 뿐이고, 프로세스는 거기에 자기 메모리 공간과 열어 둔 파일 목록과 현재 진행 상태가 붙은 살아 있는 실체입니다. 같은 프로그램을 두 번 실행하면 프로세스는 둘이고 서로의 메모리를 볼 수 없습니다. 그런데 프로세스마다 메모리를 통째로 나누다 보니, 협력해야 하는 작업끼리도 데이터를 주고받기가 번거로웠습니다. 그래서 등장한 것이 스레드(thread)입니다. 스레드는 같은 프로세스 안에서 메모리를 공유하면서 실행 흐름만 따로 가진 단위입니다. 웹 브라우저가 화면을 그리면서 동시에 파일을 내려받을 수 있는 것이 이 구조 덕분이죠. 공유가 장점인 만큼 위험도 같이 옵니다. 두 스레드가 같은 값을 동시에 고치면 어느 쪽이 먼저인지에 따라 결과가 달라지는데, 이것을 경쟁 상태(race condition)라고 부릅니다. 재현되지 않는 버그의 상당수가 여기서 나옵니다.

문맥 교환과 스케줄링

실행 주체를 바꾸려면 지금 하던 일을 고스란히 저장해 둬야 합니다. 레지스터 값들, 프로그램 카운터, 스택의 위치까지 통째로 갈무리했다가 나중에 그대로 되돌려 놓는 작업을 문맥 교환(context switch)이라고 합니다. 공짜가 아닙니다. 저장하고 복원하는 시간 자체도 들지만, 더 큰 비용은 눈에 보이지 않는 쪽에 있습니다. 새 프로세스가 올라오면 캐시에 쌓여 있던 이전 프로세스의 데이터가 밀려나므로, 돌아온 프로세스는 한동안 느리게 시작합니다. 그렇다면 누구에게 다음 차례를 줄까요. 이 결정을 내리는 것이 스케줄러이고, 목표들이 서로 충돌한다는 점이 이 문제의 본질입니다. 짧은 작업을 먼저 처리하면 평균 응답이 좋아지지만 긴 작업이 계속 밀려 굶주릴 수 있고, 순서대로 공평하게 돌리면 마우스 커서가 끊깁니다. 현대 운영체제는 선점형(preemptive) 방식을 씁니다. 프로그램이 자발적으로 양보하기를 기다리지 않고, 타이머가 울리면 운영체제가 강제로 CPU를 회수하는 것이죠. 프로그램 하나가 무한 루프에 빠져도 컴퓨터 전체가 멈추지 않는 이유입니다.

가상 메모리라는 성공한 거짓말

프로그램을 짤 때 우리는 다른 프로그램이 메모리 어디를 쓰는지 신경 쓰지 않습니다. 이 편안함은 거대한 착각 위에 서 있습니다. 운영체제와 CPU의 메모리 관리 장치는 각 프로세스에게 자기만 쓰는 연속된 주소 공간이 있다고 믿게 만듭니다. 프로그램이 다루는 주소는 가상 주소이고, 실제 물리 메모리의 위치와는 다릅니다. 둘을 잇는 것은 페이지 테이블이라는 대응표이고, 주소 변환은 하드웨어가 매 접근마다 수행하며, 자주 쓰는 변환 결과는 TLB라는 작은 캐시에 담아 둡니다. 이 한 겹의 간접 참조가 세 가지를 한꺼번에 해결합니다. 첫째, 프로세스마다 대응표가 다르므로 남의 메모리를 아예 가리킬 수 없어 격리가 성립합니다. 둘째, 물리적으로 흩어진 조각들을 연속된 것처럼 보여 주니 단편화가 완화됩니다. 셋째, 당장 안 쓰는 페이지를 디스크로 내보냈다가 필요할 때 되불러올 수 있어 실제 메모리보다 큰 프로그램도 돌아갑니다. 다만 마지막 능력은 대가가 큽니다. 접근한 페이지가 물리 메모리에 올라와 있지 않으면 하드웨어가 예외를 일으켜 운영체제에 처리를 넘기는데, 이 사건을 페이지 폴트라고 합니다. 그중에서도 디스크까지 내려가 페이지를 읽어 와야 하는 경우가 비싸고, 이것이 너무 잦아지면 시스템이 페이지를 옮기는 데만 시간을 쓰며 사실상 멈춥니다. 이 상태를 스래싱(thrashing)이라고 부릅니다.

파일 시스템과 두 개의 모드

저장 장치의 실체는 번호 붙은 블록의 나열입니다. 여기에 이름과 폴더 구조와 권한과 수정 시각을 얹어 우리가 아는 모습으로 만드는 것이 파일 시스템입니다. 어떤 파일이 어느 블록들에 흩어져 있는지는 별도의 관리 자료에 적히고, 쓰는 도중 전원이 나가도 상태가 깨지지 않도록 저널링 같은 기법이 동원됩니다. 마지막으로, 이 모든 통제가 실제로 강제되려면 응용 프로그램이 규칙을 우회할 수 없어야 합니다. 그래서 CPU는 커널 모드사용자 모드라는 두 개의 특권 수준을 하드웨어로 지원합니다. 사용자 모드에서는 페이지 테이블을 바꾸거나 장치를 직접 건드리는 명령이 아예 실행되지 않습니다. 응용 프로그램이 파일을 읽으려면 시스템 호출(system call)로 커널에 요청을 넘겨야 하고, 그 순간 제어가 정해진 진입점을 통해 커널로 넘어갔다가 돌아옵니다. 이 문턱이 있기에 프로그램 하나의 오류가 시스템 전체를 무너뜨리지 않습니다. 자원을 나눠 쓰는 기술의 마지막 조각은 결국 하드웨어가 뒷받침하는 경계선이었던 셈입니다.

인출 문제

문제 1. 프로세스와 스레드의 차이를 옳게 설명한 것은 무엇일까요?
갈라지는 지점은 주소 공간의 공유 여부입니다. 프로세스끼리는 서로의 메모리를 볼 수 없지만 같은 프로세스의 스레드들은 메모리를 공유하죠. 그래서 스레드는 데이터를 주고받기 쉬운 대신 경쟁 상태라는 위험을 안습니다.
문제 2. 선점형 스케줄링이 보장하는 것은 무엇일까요?
선점의 요점은 타이머 인터럽트로 실행권을 강제 회수한다는 것입니다. 그래서 무한 루프에 빠진 프로그램이 시스템 전체를 잠그지 못하죠. 완전한 균등 배분이나 짧은 작업 우선은 스케줄링 정책의 선택지일 뿐이고, 문맥 교환 비용은 선점 방식에서 오히려 늘어납니다.
문제 3. 가상 메모리가 프로세스 격리를 만들어 내는 방식은 무엇일까요?
프로그램이 쓰는 주소는 가상 주소이고, 프로세스마다 다른 페이지 테이블을 거쳐 물리 주소로 변환됩니다. 자기 표에 없는 물리 주소는 표현할 방법 자체가 없으니 격리가 성립하죠. 이 변환은 하드웨어가 매 접근마다 처리하므로 커널이 일일이 검사하는 방식이 아닙니다.
문제 4. 커널 모드와 사용자 모드를 하드웨어가 구분하는 이유는 무엇일까요?
특권 수준은 격리와 보호를 소프트웨어의 선의가 아니라 하드웨어로 강제하기 위한 장치입니다. 사용자 모드에서는 특권 명령이 아예 실행되지 않고, 필요한 작업은 시스템 호출로 정해진 진입점을 통해 커널에 요청해야 하죠. 실행 속도나 저장 위치와는 관계가 없습니다.

생각해볼 질문 (정답 없음)

  • 운영체제는 프로그램에게 CPU와 메모리를 독차지하고 있다는 착각을 심어 줍니다. 이 착각이 새는 순간(성능이 갑자기 느려지거나 다른 프로그램 때문에 멈추는 순간) 우리는 비로소 진짜 구조를 봅니다. 좋은 추상화란 절대 새지 않는 것일까요, 아니면 샐 때 무슨 일이 일어나는지 알려 주는 것일까요.

이전: 컴퓨터의 원리 3강 · 다음: 알고리즘과 자료구조 1강

모던지 · 궁금하면 모던지 GitHub · 2026-09-10