컴퓨터 시스템은 하드웨어와 시스템 소프트웨어로 구성되며, 이들이 함께 작동하여 응용프로그램을 실행한다.
시스템 내를 관통하는 전기적 배선군을 버스(bus)라고 하며, 컴포넌트들 간에 바이트 정보들을 전송한다. 버스는 일반적으로 워드(word)라고 하는 고정 크기의 바이트 단위로 데이터를 전송하도록 설계된다. 한 개의 워드를 구성하는 바이트 수는 시스템마다 보유하는 기본 시스템 변수다. 오늘날 대부분의 컴퓨터들은 4바이트(32비트) 또는 8바이트(64비트) 워드 크기를 갖는다.
입출력 장치는 시스템과 외부세계와의 연결을 담당한다.
메인 메모리는 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치다. 물리적으로 메인 메모리는 DRAM(Dynamic Random Access Memory) 칩들로 구성되어 있다. 논리적으로 메모리는 연속적인 바이트들의 배열로, 각각 0부터 시작해서 고유의 주소(배열의 인덱스)를 가지고 있다.
일반적으로 한 개의 프로그램을 구성하는 각 기계어 인스트럭션은 다양한 바이트 크기를 갖는다. C 프로그램 변수들의 데이터 크기는 데이터 형에 따라 다르다. 리눅스가 동작하는 x86-64 컴퓨터에서 short 타입의 데이터는 2바이트를, int, float은 4바이트, long과 double은 8바이트를 필요로 한다.
주처리장치(CPU) 또는 간단히 프로세서는 메인 메모리에 저장된 인스트럭션들을 해독(실행)하는 엔진이다. 프로세서의 중심에는 워드 크기의 저장장치(또는 레지스터)인 프로그램 카운터(PC)가 있다.
시스템에 전원이 공급되는 순간부터 전원이 끊어질 때까지 프로세서는 프로그램 카운터가 가리키는 곳의 인스트럭션을 반복적으로 실행하고 PC값이 다음 인스트럭션의 위치를 가리키도록 업데이트 한다.
프로세서는 자신의 인스트럭션 집합 구조(instruction set architecture)로 정의되는 매우 단순한 인스트럭션 실행 모델을 따라 작동하는 것처럼 보인다.
시스템 내를 관통하는 배선군을 버스라고 하며, 컴포넌트들 간에 바이트 정보들을 전송한다. 버스는 일반적으로 워드(word)라고 하는 고정 크기의 바이트 단위로 데이터를 전송하도록 설계한다.
입출력 장치는 시스템을 외부와 연결한다.
메인 메모리는 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치다. 물리적으로 메인 메모리는 DRAM(Dynamic Random Access Memory) 칩들로 구성되어 있다. 논리적으로 메모리는 연속적인 바이트들의 배열로, 각각 0부터 시작해서 고유의 주소(배열의 인덱스)를 가지고 있다.
리눅스가 작동하는 x86-64 컴퓨터에서 short 타입의 데이터는 2바이트를, int, float은 4바이트, long과 double은 8바이트의 메모리를 필요로 한다.
주처리 장치(CPU:Central Processing Unit) 또는 프로세서는 메인 메모리에 저장된 인스트럭션들을 실행하는 엔진이다. 프로세서의 중심에는 워드 크기의 저장장치(레지스터)인 프로그램 카운터(PC)가 있다.
시스템은 정보를 한 곳에서 다른 곳으로 이동시키는 일에 많은 시간을 보낸다.
프로그램의 기계어 인스트럭션들은 본래 하드 디스크에 저장되어 있다. 프로그램이 로딩될 때 이들은 메인 메모리로 복사된다. 프로세서가 프로그램을 실행할 때 인스트럭션들은 메인 메모리에서 프로세서로 복사된다.
프로세서-메모리 간 격차에 대응하기 위해 시스템 설계자는 보다 작고 빠른 캐시 메모리라고 부르는 저장장치를 고안하여 프로세서가 단기간에 필요로 할 가능성이 높은 정보를 임시로 저장할 목적으로 사용한다.
L1, L2 캐시는 SRAM(Static Random Access Memory)이라는 하드웨어 기술을 이용해 구현한다.
모든 컴퓨터 시스템의 저장장치들은 메모리 계층구조로 구성되어 있다.
레지스터 파일은 계층구조의 최상위인 레벨 0, L0을 차지한다.
메인 메모리는 레벨 4에 위치한다.
메모리 계층구조의 주요 아이디어는 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다는 것이다.
운영체제(operating system)은 두 가지 목적을 가진다.
(1) 동작하는 응용 프로그램들이 하드웨어를 잘못 사용하는 것을 막기 위해
(2) 응용 프로그램들이 단순하고 균일한 메커니즘을 사용하여 복잡하고 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 하기 위해
운영체제는 프로세스, 가상 메모리, 파일의 근본적인 추상화를 통해 두 가지 목표를 달성한다.
파일은 입출력 장치의 추상화이다.
가상 메모리는 메인 메모리와 디스크 입출력 장치의 추상화이다.
프로세스는 프로세서, 메인 메모리, 입출력 장치 모두의 추상화이다.
프로세스는 실행 중인 프로그램에 대한 운영체제의 추상화다.
다수의 프로세스들은 동일한 시스템에서 동시에 실행될 수 있다.
운영체제는 문맥 전환(context switching)이라는 방법을 사용해서 교차 실행을 수행한다.
운영체제는 프로세스가 실행하는 데 필요한 모든 상태정보의 변화를 추적한다.
컨텍스트라고 부르는 상태정보는 PC, 레지스터 파일, 메인 메모리의 현재 값을 포함하고 있다.
운영체제는 현재 프로세서에서 다른 새로운 프로세스로 제어를 옮기려고 할 때 현재 프로세스의 컨텍스트를 저장하고 새 프로세스의 컨텍스트를 복원시키는 문맥전환을 실행하여 제어권을 새 프로세스로 넘겨준다.
쉘은 시스템 콜이라는 특수 함수를 호출하여 운영체제로 제어권을 넘겨준다.
하나의 프로세스에서 다른 프로세스로의 전환은 운영체제 커널(kernel)에 의해 관리된다.
커널은 모든 프로세스를 관리하기 위해 시스템이 이용하는 코드와 자료 구조의 집합으로, 운영체제 코드의 일부분으로 메모리에 상주하며 별도의 프로세스가 아니다.
응용 프로그램이 운영체제에 의한 어떤 작업을 요청하면, 컴퓨터는 파일 읽기나 쓰기와 같은 특정 시스템 콜(system call)을 실행해서 커널에 제어를 리턴한다.
프로세스가 마치 한 개의 제어흐름을 갖는 것으로 생각할 수 있지만, 최근의 시스템에서는 프로세스가 실제로 쓰레드(thread)라고 하는 다수의 실행 유닛으로 구성되어 있다.
각각의 쓰레드는 해당 프로세스의 컨텍스트에서 실행되며 동일한 코드와 전역 데이터를 공유한다.
가상 메모리는 각 프로세스들이 메인 메모리 전체를 독점적으로 사용하고 있는 것 같은 환상을 제공하는 추상화이다.
각 프로세스는 가상주소 공간이라고 하는 균일한 메모리의 모습을 갖는다.
리눅스에서 주소공간의 최상위 영역은 모든 프로세스들이 공통으로 사용하는 운영체제의 코드와 데이터를 위한 공간이다.
주소공간의 하위 영역은 사용자 프로세스의 코드와 데이터를 저장한다.
힙(heap): 코드와 데이터 영역 다음으로 런타임 힙이 따라온다. 크기가 고정되어 있는 코드, 데이터 영역과 달리, 힙은 프로세스가 실행되면서 C 표준 함수인 malloc이나 free를 호출하면 런타임에 동적으로 그 크기가 늘었다 줄었다 한다.
공유 라이브러리: 주소공간의 중간 부근에 C 표준 라이브러리와 같은 공유 라이브러리의 코드와 데이터를 저장하는 영역이 존재한다.
스택(stack): 사용자 가상 메모리 공간의 맨 위에 컴파일러가 함수 호출을 구현하기 위해 사용하는 사용자 스택이 위치한다. 사용자 스택은 프로그램이 실행되는 동안에 동적으로 늘어났다 줄어들었다 한다. 함수를 호출할 때마다 스택이 커지며, 함수에서 리턴될 때는 줄어든다.
커널 가상 메모리: 주소 공간의 맨 윗부분은 커널을 위해 예약되어 있다. 응용 프로그램들은 이 영역의 내용을 읽거나 쓰는 것이 금지되어 있으며, 마찬가지로 커널 코드 내에 정의된 함수를 직접 호출하는 것도 금지되어 있다. 이런 작업을 수행하기 위해 커널을 호출해야 한다.
가상 메모리가 작동하기 위해서는 프로세서가 만들어내는 모든 주소를 하드웨어로 번역하는 등의 하드웨어와 소프트웨어 간의 상호작용이 필요하다.
기본적인 아이디어는 프로세스의 가상 메모리의 내용을 디스크에 저장하고 메인 메모리를 디스크의 캐시로 사용하는 것이다.
파일은 연속된 바이트들로 시스템의 모든 입출력은 유닉스 I/O라는 시스템 콜들을 이용하여 파일을 읽고 쓰는 형태로 이루어진다.
동시성(concurrency)는 다수의 동시에 벌어지는 일을 갖는 시스템에 대한 일반적인 개념을 의미한다.
병렬성(parallelism)은 동시성을 사용해서 시스템을 보다 빠르게 동작하도록 하는 것을 의미한다.
프로세스 추상화 개념을 이용하면 다수의 프로그램이 동시에 실행되는 시스템을 생각할 수 있다.
쓰레드를 이용하면 한 개의 프로세스 내에서 실행되는 다수의 제어흐름을 가질 수 있는 시스템 구성을 단일 프로세서 시스템이라고 한다.
어떤 시스템이 여러 개의 프로세서를 가지고 하나의 운영체제 커널의 제어 하에 동작하는 경우를 멀티프로세서 시스템이라고 한다.
멀티쓰레딩이라고도 하는 하이퍼쓰레딩은 하나의 CPU가 여러 개의 제어 흐름을 실행할 수 있게 해주는 기술이다.
프로그램 카운터나 레지스터 파일 같은 여러 개의 동일한 CPU 하드웨어를 가지고 있는 반면, 부동소수 연산기와 같은 다른 부분들은 한 개의 하드웨어만 가지고 있는 구조와 관련되어 있다.
컴퓨터 시스템은 응용 프로그램을 실행하기 위해 함께 동작하는 하드웨어와 시스템 소프트웨어로 구성된다.
프로세서는 메인 메모리에 저장된 바이너리 인스트럭션을 읽고 해석한다.
컴퓨터가 대부분의 시간을 메모리, 입출력 장치, CPU 레지스터 간에 데이터를 복사하는 데 쓰고 있으므로 시스템의 저장장치들은 계층 구조를 형성하여 CPU 레지스터가 최상위에, 하드웨어 캐시 메모리, DRAM 메인 메모리, 디스크 저장장치 등이 순차적으로 위치한다.
계층 구조 상부의 저장장치들은 하부의 장치들을 위한 캐시 역할을 수행한다.
운영체제 커널은 응용 프로그램과 하드웨어 사이에서 중간자의 역할을 수행한다.
운영체제는 세 가지 근본적인 추상화를 제공한다.
(1) 파일은 입출력 장치의 추상화다.
(2) 가상 메모리는 메인 메모리와 디스크의 추상화다.
(3) 프로세스는 프로세서, 메인 메모리, 입출력 장치의 추상화다.
네트워크는 컴퓨터 시스템이 서로 통신할 수 있는 방법을 제공한다.