Link

1장: 컴퓨터 시스템으로의 여행

프로세서는 메모리에 저장된 명령어를 읽고 해석한다

시스템의 하드웨어 조직

컴퓨터 하드웨어 조직 버스
시스템 내를 관통하는 전기적 배선군을 버스bus라고 하며, 컴포넌트 간에 바이트 정보들을 전송한다. 버스는 일반적으로 워드word라고 하는 고정크기의 바이트 단위로 데이터를 전송하도록 설계된다.

입출력 장치
각 입출력 장치는 입출력 버스와 컨트롤러나 어댑터를 통해 연결된다. 이 두 장치의 차이는 패키징에 있다. 컨트롤러는 디바이스 자체가 칩셋이거나 시스템의 마더보드에 장착된다. 어댑터는 마더보드의 슬롯에 장착되는 카드이다.

직접 메모리 접근(DMA)
DMA는 프로세서(CPU)의 개입 없이 장치로부터 메모리로 데이터를 전송하는 기법을 말한다.

캐시가 중요하다

프로세서는 레지스터 파일의 데이터를 메모리의 경우보다 거의 100배 더 빨리 읽을 수 있다. 더욱 난감한 것은 반도체 기술이 매년 발달함에 따라 이와 같은 프로세서-메모리 간 격차가 지속적으로 증가하고 있다는 것이다.

프로세서-메모리 간 격차에 대응하기 위해 시스템 설계자는 보다 작고 빠른 캐시 메모리라고 부르는 저장장치를 고안하여 프로세서가 단기간에 필요로 할 가능성이 높은 정보를 임시로 저장할 목적으로 사용한다.

프로세서 칩 내에 들어 있는 L1 캐시는 대략 수천 바이트의 데이터를 저장할 수 있으며, 거의 레지스터 파일만큼 빠른 속도로 접근할 수 있다. 이보다 좀더 큰 L2 캐시는 수백 킬로바이트에서 수 메가 바이트의 용량을 가지며 프로세서와 전용 버스를 통해 연결된다. 프로세서가 L2 캐시를 접근할 때 L1 캐시보다 5배 정도 느리지만, 그래도 여전히 메인 메모리를 접근할 때보다는 5배에서 크게는 10배까지 더 빠르다. L1, L2 캐시는 SRAM이라는 하드웨어 기술을 이용해 구현한다. 보다 새롭고 강력한 시스템은 심지어 3단계의 캐시를 갖는 경우도 있다.

캐시 시스템의 이면에 깔려 있는 아이디어는 프로그램이 지엽적인 영역의 코드와 데이터를 접근하는 경향인 지역성locality을 활용하여, 매우 큰 메모리와 매우 빠른 메모리의 효과를 시스템이 얻을 수 있다는 것이다.

저장장치들은 계층구조를 이룬다

사실 모든 컴퓨터 시스템의 저장장치들은 그림과 같은 메모리 계층구조memory hierarchy로 구성되어 있다. 계층의 꼭대기에서부터 맨 밑바닥까지 이동할수록 저장장치들은 더 느리고, 더 크고, 바이트당 가격이 싸진다. 메모리 계층구조의 주요 아이디어는 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다는 것이다. L1과 L2의 캐시는 각각 L2와 L3의 캐시인 것이다. L3 캐시는 메인 메모리의 캐시이고, 이 캐시는 디스크의 캐시 역할을 한다. 일부 분산 파일시스템을 가지는 네트워크 시스템에서 로컬 디스크는 다른 시스템의 디스크에 저장된 데이터의 캐시 역할을 수행한다.
메모리 계층구조

운영체제는 하드웨어를 관리한다

운영체제는 하드웨어와 소프트웨어 사이에 위치한 소프트웨어 계층으로 생각할 수 있다. 응용 프로그램이 하드웨어를 제어하려면 언제나 운영체제를 통해서 해야 한다.

컴퓨터 시스템의 계층화

운영체제는 두 가지 주요 목적을 가지고 있다.

  • 제멋대로 동작하는 응용 프로그램들이 하드웨어를 잘못 사용하는 것을 방지한다.
  • 응용 프로그램들이 단순하고 균일한 메커니즘을 사용하여 복잡하고 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 해준다.

운영체제는 이 두 가지 목표를 근본적인 추상화를 통해 달성하고 있다: 프로세스, 가상메모리, 파일 운영체제에 의한 추상화 이 그림이 보여주는 것처럼 파일은 입출력 장치의 추상화이고, 가상메모리는 메인 메모리와 디스크 입출력 장치의 추상화, 그리고 프로세스는 프로세서, 메인 메모리, 입출력 장치 모두의 추상화 결과이다.

프로세스

프로세스는 실행 중인 프로그램에 대한 운영체제의 추상화다. 다수의 프로세스든 동일한 시스템에서 동시에 실행될 수 있으며, 각 프로세스는 하드웨어를 배타적으로 사용하는 것처럼 느낀다.

대부분의 시스템에서 프로세스를 실행할 CPU의 숫자보다 더 많은 프로세스들이 존재한다. 프로세서가 프로세스들을 바꿔주는 방식으로 한 개의 CPU가 다수의 프로세스를 동시에 실행하는 것처럼 보이게 해준다. 운영체제는 문맥 전환context switching이라는 방법을 사용해서 이러한 교차실행을 수행한다.

  • 컨텍스트(context): 프로세스가 가지고 있는 상태 정보. PC, 레지스터 파일, 메인 메모리의 현재 값 등을 포함한다. 운영체제는 현재 프로세스에서 다른 새로운 프로세스로 제어를 옮기려고 할 때 현재 프로세스의 컨텍스트를 저장하고 새 프로세스의 컨텍스트를 복원시키는 문맥전환을 실행하여 제어권을 새 프로세스로 넘겨준다. 새 프로세스는 이전에 중단했던 바로 그 위치부터 다시 실행된다.
  • 시스템 콜(system call)과 커널: 시스템 콜은 특수한 함수로, 사용자 프로그램이 시스템 콜을 호출하면 제어가 커널에게 넘어간다.

쓰레드

요즘의 시스템에서는 프로세스가 쓰레드Thread라고 하는 다수의 실행 유닛으로 구성되어 있다. 각각의 쓰레드는 해당 프로세스의 컨텍스트에서 실행되며 동일한 코드를 가지고, 전역 데이터를 공유한다. 쓰레드는 다수의 프로세스보다 데이터의 공유가 더 쉽다는 점과 효율적이라는 점 때문에 프로그래밍 모델로서의 중요성이 더욱 커지고 있다.

가상메모리

가상메모리는 각 프로세스들이 메인 메모리 전체를 독점적으로 사용하고 있는 것 같은 환상을 제공하는 추상화이다. 각 프로세스는 가상 주소공간이라고 하는 균일한 메모리의 형태를 갖게 된다. 다음 그림은 리눅스 프로세스의 가상 주소공간을 나타낸 것이다. 가상 주소공간

  • 프로그램 코드와 데이터: 코드는 모든 프로세스들이 같은 고정주소에서 시작하며, 다음에 C 전역변수에 대응되는 데이터 위치들이 따라온다. 코드와 데이터 영역은 실행 가능 목적파일로부터 직접 초기화된다.
  • 힙(heap): 코드와 데이터 영역 다음으로 런타임 힙이 위치한다. 힙은 C 표준함수인 malloc이나 free를 호출하면서 런타임에 동적으로 그 크기가 늘었다 줄었다 한다.
  • 공유 라이브러리: 주소공간의 중간 부근에 C 표준 라이브러리나 수학 라이브러리와 같은 공유 라이브러리의 코드와 데이터를 저장하는 영역이 있다.
  • 스택(stack): 사용자 가상메모리 공간의 맨 위에 컴파일러가 함수 호출을 구현하기 위해 사용하는 사용자 스택이 위치한다. 힙과 마찬가지로 사용자 스택은 프로그램이 실행되는 동안에 동적으로 늘어났다 줄어들었다 한다.
  • 커널 가상메모리: 커널은 메모리에 상주하는 운영체제의 일부분이다. 주소공간의 맨 윗부분은 커널을 위해 예약되어 있다. 응용 프로그램들은 이 영역의 내용을 읽거나 쓰는 것이 금지되어 있으며, 커널 코드 내에 정의된 함수를 직접 호출하는 것도 마찬가지로 금지되어 있다.

가상메모리가 작동하기 위해서는 프로세서가 만들어 내는 모든 주소(가상 주소)를 하드웨어로 번역하는 등의 하드웨어와 운영체제 소프트웨어 간의 복잡한 상호작용이 필요하다. 기본적인 아이디어는 프로세스의 가상 메모리 내용을 디스크에 저장하고 메인 메모리를 디스크의 캐시로 사용하는 것이다.

파일

파일은 더도 덜도 말고 그저 연속된 바이트들이다. 디스크, 키보드, 디스플레이, 네트워크까지를 포함하는 모든 입출력 장치는 파일로 모델링한다. 시스템의 모든 입출력은 유닉스 I/O라는 시스템 콜들을 이용하여 파일을 읽고 쓰는 형태로 이루어진다. 이러한 파일 개념은 매우 강력해서 시스템에 들어 있는 다양한 입출력 장치들의 통일된 뷰를 응용 프로그램에 제공한다.

시스템은 다른 시스템과 네트워크를 사용하여 통신한다

네트워크 역시 일종의 입출력 장치다. 네트워크를 입출력의 확장이라고 생각하면 된다.

중요한 주제들

동시성(concurrency)과 병렬성(parallelism)

  • 동시성(concurrency): 다수의 동시에 벌어지는 일을 갖는 시스템에 관한 일반적인 개념을 말할 때 사용한다.
  • 병렬성(parallelism): 동시성을 사용해서 시스템을 보다 빠르게 동작하도록 하는 것을 말할 때 사용한다.

쓰레드 수준 동시성

  • 단일프로세서 시스템
  • 멀티프로세서 시스템
  • 멀티코어 프로세서, 하이퍼쓰레딩(hyperthreading)
  • 하이퍼쓰레딩: 멀티쓰레딩이라고도 하며, 하나의 CPU가 여러 개의 제어 흐름을 실행할 수 있게 해주는 기술이다.

명령어 수준 병렬성

  • 파이프라이닝(pipelining)과 단계(stage)
  • 슈퍼스칼라(superscalar)

단일 명령어, 다중 데이터 병렬성(SIMD) 많은 최신 프로세서들은 최하위 수준에서 단일 명령어, 다중 데이터, 즉 SIMD 병렬성이라는 모드로 한 개의 명령어가 병렬로 다수의 연산을 수행할 수 있는 특수 하드웨어를 가지고 있다.