컴퓨터 시스템의 전반적인 구조부터 인터럽트와 입출력, 저장 장치, 그리고 보안에 대해서 다뤄보자.
1. 컴퓨터 시스템의 구조
컴퓨터 시스템은 크게 다음과 같이 나눌 수 있다.
구분 | 예시 |
---|---|
내부 장치 | CPU, 메모리 등 |
외부 장치 (입출력 장치) | 디스크, 키보드, 마우스, 모니터, 네트워크 장치 등 |
또한, 컴퓨터 시스템의 동작 원리를 알기 위해 알아야 할 것에는 다음의 것들이 있다.
각 외부 하드웨어 장치에 존재하며, 해당 장치를 제어하는 일종의 CPU를 컨트롤러(controller)라고 한다.
ex) 메모리 컨트롤러, 디스크 컨트롤러 등
- 프로그램이 수행되려면 그 프로그램이 메모리에 올라가 있어야 한다.
- 운영체제 중 항상 메모리에 올라가 있는 핵심적인 부분을 커널(kernel)이라 한다.
2. 인터럽트 (Interrupt)
CPU 연산, I/O 연산
입출력 장치와 메인 CPU는 동시 수행이 가능하므로, CPU 연산과 I/O 연산은 동시에 진행될 수 있다. 그렇다면 CPU는 어떻게 I/O 작업이 완료되었음을 알 수 있을까?
연산 종류 | 담당 |
---|---|
CPU 연산 | 메인 CPU |
I/O 연산 | 입출력 컨트롤러 |
우선, 각 장치의 컨트롤러는 장치로부터 들어가고 나오는 데이터를 임시로 저장하기 위해 로컬버퍼(local buffer)라는 작은 메모리를 가지고 있다. 즉, I/O 작업이란 디스크나 키보드 등의 외부 장치 → 로컬버퍼로 데이터를 읽어오는 작업이다.
이러한 I/O 작업이 완료되면 컨트롤러가 인터럽트를 발생시켜 CPU에게 보고하게 되며, 인터럽트 방식을 통해 메인 CPU는 I/O 작업이 끝났는지를 지속적으로 체크하지 않아도 된다.
외부 장치에서 데이터를 읽어오는 경우, 데이터의 저장 위치
인터럽트, 인터럽트 처리루틴
인터럽트 (Interrupt)
컨트롤러가 CPU의 서비스가 필요할 때나 CPU에 알려줄 필요가 있는 이벤트가 일어난 경우 이를 통보하는 방법이다.
- CPU는 명령 하나를 수행할 때마다 인터럽트가 발생했는지 확인하여, 인터럽트가 발생한 경우 다음 명령을 수행하기 전에 인터럽트 처리를 한다.
- CPU 옆에는 인터럽트 라인이 있어, CPU가 자신의 작업을 하던 중간에 인터럽트 라인에 신호가 들어오면 하던 일을 멈추고 인터럽트와 관련된 일을 먼저 처리한다.
인터럽트 처리루틴 (Interrupt Service Routine)
운영체제 커널 내에 존재하며, 다양한 인터럽트에 대해 각각 처리해야 할 업무들을 정의한다.
인터럽트의 종류
CPU 옆의 인터럽트 라인에 신호를 보내 인터럽트가 발생했음을 알려주는 방식은 동일하다.
구분 | 통상적인 이름 | 설명 |
---|---|---|
하드웨어 인터럽트 | 인터럽트 | 하드웨어 장치(ex. 컨트롤러)가 CPU의 인터럽트 라인을 세팅 |
소프트웨어 인터럽트 | 트랩(trap) | 소프트웨어가 CPU의 인터럽트 라인을 세팅 |
소프트웨어 인터럽트 (트랩, trap)
구분 | 설명 |
---|---|
예외상황(exception) | 비정상적인 작업을 시도하거나 권한이 없는 작업을 시도할 때 발생시키는 인터럽트 |
시스템 콜(system call) | 사용자 프로그램이 운영체제 내부에 정의된 코드를 실행하고 싶을 때 운영체제에 서비스를 요청하는 방법 (ex. 입출력 작업) |
- CPU의 제어권이 <사용자 프로세스 → 운영체제>로 이양된다.
- 프로그램 코드가 직접 인터럽트 라인을 세팅하는 명령을 실행하여 인터럽트를 발생시킨다.
인터럽트 핸들링 (Interrupt Handling)
인터럽트가 발생한 경우에 처리해야 할 일의 절차를 의미한다.
어떤 프로그램이 실행되던 중 인터럽트가 발생하면, 해당 프로그램의 실행 상태를 PCB에 저장한다.
프로세스 제어블록(PCB; Process Control Block)
- 운영체제가 현재 시스템 내에서 실행되는 프로그램들을 관리하기 위해 가지고 있는 자료구조로, 각 프로그램마다 하나씩 존재한다.
- 저장하는 값: 프로그램이 실행 중이던 코드의 메모리 주소, 레지스터 값, 하드웨어 상태, …
- 운영체제 커널 내에서 해당 인터럽트의 처리를 위해 정의된 코드를 찾는다. (→ 인터럽트 벡터)
- CPU의 제어권이 인터럽트 처리루틴으로 넘어가고, 인터럽트 처리루틴을 통해 인터럽트를 처리한다.
- 인터럽트 처리가 끝나면 저장된 상태를 PCB로부터 CPU 상에 복원한다.
- 인터럽트 발생 직전에 실행하던 위치부터 이어서 실행한다.
구분 | 설명 |
---|---|
인터럽트 벡터(interrupt vector) | 인터럽트 종류마다 번호를 지정하여, 번호에 따라 처리해야 할 코드가 위치한 부분을 가리키고 있는 자료구조 |
인터럽트 처리루틴(interrupt service routine) / 인터럽트 핸들러(interrupt handler) | 인터럽트 발생 시 실제로 처리해야 할 코드 |
운영체제가 CPU를 점유하는 경우는 인터럽트가 발생할 때가 유일하다.
- 시스템이 부팅 후 정상 상태에 도달하면 CPU는 항상 사용자 프로그램에 의해서만 사용된다.
- 단지 인터럽트가 발생했을 때에만 잠깐 운영체제의 코드 부분으로 CPU가 이양된다.
3. 입출력 (I/O)
컴퓨터 시스템이 컴퓨터 외부의 입출력 장치들과 데이터를 주고 받는 것
입출력의 종류
- 동기식 입출력 (synchronous I/O): 어떤 프로그램이 입출력 요청 시, 입출력 작업이 완료된 후에야 그 프로그램이 후속 작업을 수행할 수 있는 방식
- 비동기식 입출력 (asynchronous I/O): 입출력 연산을 요청한 후, CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 곧바로 다시 부여하는 방식
[1] 동기식 입출력 (Synchronous I/O)
일반적인 방법이다.
- 입출력이 진행되는 동안 프로그램의 다음 명령을 수행하지 않고 대기한다.
- 입출력 요청이 발생하면 운영체제의 커널로 CPU의 제어권이 넘어와서 입출력 처리와 관련된 커널의 코드가 수행된다.
- 일반적으로 입출력을 수행 중인 경우, CPU를 다른 프로그램에게 이양하여 CPU가 쉬지 않고 일할 수 있도록 관리한다. (→ 동시에 다수의 입출력 연산 가능)
- 그렇지 않으면 입출력 연산 완료 인터럽트를 기다리며 자원(CPU)을 낭비하게 된다.
- 입출력 중인 프로그램의 경우, blocked state로 전환하여 CPU를 할당하지 않는다.
- 다수의 동시 입출력 요청의 동기화를 위해 장치별로 큐(queue)를 두어 요청한 순서대로 처리할 수 있도록 한다.
- 동기식 입출력에서는 동기화가 자동으로 이루어질 수 있으나, 입출력이 수행 중일 때 CPU를 양도 받은 다른 프로그램도 동일한 입출력 장치에 대해 연산을 수행하면 순서가 바뀌는 등 의도하지 않은 결과가 발생할 수 있기 때문이다.
- 요청들을 모으고 처리 순서를 바꾸어 입출력의 효율성을 높일 수도 있다.
- 컨트롤러는 요청된 입출력 연산이 완료되면 인터럽트를 통해 CPU에게 입출력 연산이 완료되었음을 알린다.
- 운영체제 커널은 인터럽트 처리루틴으로 가서 입출력 연산을 끝낸 프로그램이 CPU를 할당받을 수 있도록 프로그램의 상태를
blocked
state로부터 해제시킨다. - 일반적으로 해당 프로그램의 입출력이 완료될 때까지 해당 프로그램을 block 시키는 동기식 입출력을 사용한다.
[2] 비동기식 입출력 (Asynchronous I/O)
- 입출력 관련 데이터와 상관없이 수행할 수 있는 작업을 먼저 수행한다.
- 동기식 입출력과 마찬가지로 입출력 연산이 완료되면 인터럽트를 통해 CPU에게 알린다.
(예시) 프로그램 A가 실행 중에 디스크에서 데이터를 읽어오는 명령을 만나게 되는 경우
- 프로그램 A는 system call(일종의 소프트웨어 인터럽트)을 발생시켜 CPU에게 입출력 요청을 알린다.
- CPU는 프로그램 A를 실행하던 것을 멈추고 현재의 상태를 PCB에 저장한다.
- CPU는 system call에 의해 처리되어야 할 커널의 루틴으로 이동한 후, 컨트롤러에게 입출력 연산을 요청한다.
- 컨트롤러는 A가 요청한 데이터를 디스크 → 로컬버퍼로 읽어온다. 그동안 프로그램 A는
blocked
state로 CPU를 할당 받지 못하며, 다른 프로그램 B에 CPU를 할당한다. - 요청한 데이터가 로컬버퍼로 다 들어오면 컨트롤러는 CPU에게 인터럽트(하드웨어 인터럽트)를 통해 입출력이 완료되었다는 사실을 알린다.
- CPU는 프로그램 B를 실행하던 것을 멈추고 현재의 상태를 PCB에 저장한다.
- 인터럽트 처리루틴을 통해 (1) A가 요청한 데이터를 로컬버퍼 → A의 메모리 영역으로 읽어오고 (2) A의 blocked state를 해제한다.
- 프로그램 A는 CPU를 기다리는 줄에 다시 서게 되며, CPU는 원래 수행하던 프로그램 B의 지점으로 돌아가 이어서 동작을 수행한다.
- 프로그램 A는 자신의 차례가 되면 CPU를 할당 받고 입출력 연산 이후의 작업을 수행한다.
DMA (Direct Memory Access)
일종의 컨트롤러로, 데이터를 장치의 <로컬버퍼 → 메모리>로 읽어오는 작업을 대행하여 CPU가 입출력 장치들의 메모리 접근 요청에 의해 자주 인터럽트 당하는 것을 방지한다.
디스크와 같은 고속 장치의 경우, 각 바이트가 전달될 때마다 인터럽트가 발생하게 된다면 인터럽트 핸들링에 많은 시간을 소요하게 된다. DMA는 이러한 오버헤드를 줄이기 위한 방법이다.
- 원칙적으로 메모리는 CPU에 의해서만 접근 가능하지만, DMA는 CPU의 개입 없이 메모리 ↔ I/O 장치 간의 데이터 교환을 제어하는 권한을 가지고 있다.
- DMA의 동작 과정
- 장치의 로컬 버퍼 내 데이터가 바이트(byte) 단위보다 큰 블록(block) 단위까지 찰 때까지 기다린다.
- 해당 데이터를 직접 메모리에 복사한다.
- 작업이 완료되면 CPU에게 인터럽트를 발생시켜 알린다. 즉, CPU는 메모리로 데이터 이동이 완료되었단는 단 한 번의 인터럽트만 받게 되는 것이다.
입출력 장치에서 데이터를 읽어오는 경우, 데이터의 저장 위치
4. 저장 장치
구분 | 특징 | 예시 |
---|---|---|
주기억장치 (메모리) | 휘발성 | RAM |
보조기억장치 | 비휘발성 | 마그네틱 디스크, 플래시 메모리, CD, 마그네틱 테이프 |
보조기억장치의 용도
- 파일 시스템 (file system)
- 메모리는 휘발성 매체이므로 비휘발성 매체인 디스크를 파일 시스템용으로 사용한다.
- 스왑 영역 (swap area)
- 프로그램이 종료될 때는 저장된 내용을 삭제하는 메모리의 연장 공간으로서의 역할을 담당한다.
- 운영체제는 프로그램 수행에 당장 필요한 부분만 메모리에 올려두고, 그렇지 않은 부분은 디스크의 swap area에 둔다.
- swap area에 내리는 것을 “swap out” 시킨다고 표현한다.
- 메모리는 크기가 제한적이고 가격이 상대적으로 비싸며 용량이 적은 경우가 대부분이기 때문이다.
하드디스크가 널리 사용된다.
하드디스크
- 암(arm)이 이동하면서 여러 개의 마그네틱 원판들에 저장된 데이터를 읽고 쓰는 방식으로 동작한다.
- 원판의 표면은 트랙(track)으로 나뉘며, 각 트랙은 최소 단위 정보인 섹터(sector)로 나뉜다.
저장 장치의 계층 구조
종류 | 위치 | 예시 | 특징 |
---|---|---|---|
휘발성 저장장치 | 상위 | 레지스터(register) 캐시 메모리(cache memory) 메인 메모리(main memory) | 접근 속도가 빠르지만 용량은 상대적으로 작고 가격이 높음 |
비휘발성 저장장치 | 하위 | 마그네틱 디스크(magnetic disk) 등 | 대용량이며 가격이 저렴하지만 접근 속도가 느림 |
- 당장 필요한 정보는 빠른 저장장치에 넣어 수행 속도를 높이고, 그렇지 않은 정보는 상대적으로 느린 저장장치에 보관한다.
- 캐시 메모리 (cache memory)
- 레지스터와 메인 메모리 사이에 존재하는 저장장치이다.
- 캐싱 기법을 이용해 작은 용량의 캐시 메모리를 통해 메인 메모리와 같이 큰 용량을 가진 것처럼 효율적으로 동작하도록 관리할 수 있다.
캐싱 기법 (Caching)
- 상대적으로 느린 저장장치에 있는 내용 중 당장 사용되거나 빈번히 사용될 정보를 빠른 저장장치에 선별적으로 저장함으로써 두 저장장치 사이의 속도 차이에서 오는 병목을 완충시키는 기법이다.
참조의 지역성 (locality of reference): 컴퓨터 프로그램이 일정 기간 동안 특정 메모리 위치 집합에 접근하는 경향 (동일한 값 또는 해당 값에 관련된 위치가 자주 액세스됨)
동일한 값 또는 해당 값에 관련된 위치가 자주 액세스되는 특성을 통해 hit-rate를 높일 수 있다.
종류 설명 예시 spatial locality 참조된 메모리 근처의 메모리가 이어서 참조되는 경향 배열을 순차적으로 탐색하는 경우 temporal locality 참조했던 메모리가 빠른 시간 내에 다시 참조되는 경향 반복문, 스택 sequential locality 데이터가 순차적으로 액세스되는 경향
(temporal locality로 설명 가능)배열을 순차적으로 탐색하는 경우 - 캐싱 기법을 컴퓨터 시스템 내의 다양한 저장장치 계층에서 활용함으로써 작은 용량의 상위 저장장치만으로도 대부분의 경우 빠른 수행 속도의 성능을 얻어낼 수 있다.
5. 보안 및 보호
커널 모드, 사용자 모드
흔히 사용하는 운영체제는 여러 프로그램이 동시에 실행될 수 있는 다중 프로그래밍(multi-programming) 환경에서 동작하기 때문에, 프로그램 간 충돌을 방지하기 위해 하드웨어에 대한 보안 기법이 필요하다.
구분 | 모드 비트 | 설명 | 실행 가능한 명령 |
---|---|---|---|
커널 모드 (kernel mode) | 0 | 운영체제가 CPU의 제어권을 가지고 운영체제 코드를 실행하는 모드 | 모든 종류의 명령 (특권 명령 포함) |
사용자 모드 (user mode) | 1 | 일반 사용자 프로그램이 실행되는 모드 | 제한적인 명령 |
특권 명령 (Privileged Instruction)
- 중요한 정보에 접근해 위험한 상황을 초래할 수 있는 연산, 즉 시스템의 보안과 관련된 명령이다.
- 모드 비트가
0
일 때, 즉 커널 모드에서 운영체제에 의해서만 수행될 수 있다. 모든 입출력 명령은 특권 명령으로, 사용자 프로그램이 직접 입출력을 수행할 수 없다.
사용자 프로그램은 system call을 통해 운영체제에 요청하여 운영체제가 입출력 명령을 대신 수행하도록 해야 한다.
모드 비트 (Mode Bit)
0
- 커널 모드 /1
- 사용자 모드- CPU 내부에 설정되는 값으로, 보안과 관련된 명령(= 특권 명령)을 수행하기 전에는 CPU는 항상 모드 비트를 조사하여 그 값이
0
으로 설정된 경우에만 명령을 수행한다. - 인터럽트가 발생할 때 모드 비트는 자동으로
0
으로 설정된다. - 운영체제가 CPU를 점유하여 동작하다가 사용자 프로그램에게 CPU 제어권을 넘길 때 모드 비트를
1
로 설정하여 넘긴다.
메모리 보안
여러 프로그램이 메모리에 동시에 올라가서 실행되므로, 하나의 사용자 프로그램이 다른 메모리 영역을 침범할 수 있다. 따라서 2개의 레지스터를 통해 프로그램이 접근하려는 메모리 부분이 합법적인지 체크하며 메모리를 보호한다.
종류 | 설명 | 보관하는 값 |
---|---|---|
기준 레지스터 (base register) | 어떤 프로그램이 수행되는 동안 그 프로그램이 합법적으로 접근할 수 있는 메모리 상의 가장 작은 주소를 보관한다. | 어떤 프로그램이 실제 메모리에 올라가 있는 부분의 시작 주소 |
한계 레지스터 (limit register) | 어떤 프로그램이 기준 레지스터 값으로부터 접근할 수 있는 메모리의 범위를 보관한다. | 해당 프로그램의 길이 |
메모리 접근 연산이 있을 때마다 하드웨어적으로 접근하려는 위치가 합법적인 범위에 있는지 체크한다.
합법적인 범위 = (기준 레지스터 값) ~ (기준 레지스터 값 + 한계 레지스터 값) 사이 주소 영역
합법적인 범위를 벗어나는 경우, 예외 상황(exception)이라는 소프트웨어 인터럽트를 발생시킨다.
CPU의 제어권을 운영체제로 이양시키고, 운영체제는 해당 프로그램을 강제로 종료시킨다.
기준/한계 레지스터를 이용한 메모리 보호 기법은 단순화된 메모리 관리 기법을 사용하는 경우에만 적용 가능하다. 페이징 기법 등을 이용하는 경우, 다른 하드웨어의 지원 또한 필요하다.
단순화된 메모리 관리 기법 하나의 프로그램이 메모리의 한 영역에 연속적으로 위치 페이징 기법 하나의 프로그램이 메모리의 여러 영역에 연속적으로 위치 메모리 접근 연산
모드 메모리 접근 커널 모드 (kernel mode) 무제한으로 접근 가능 사용자 모드 (user mode) 기준 레지스터와 한계 레지스터 사용 - 메모리 read / write 연산은 사용자 프로그램이 CPU를 가지고 있는 동안 수행할 수 있으므로 특권 명령이 아니다.
- 사용자 프로그램이 메모리에 접근하기 전, 하드웨어적으로 그 접근이 합법적인지를 체크하여 메모리를 보호하게 된다.
- 기준/한계 레지스터의 값을 설정하는 연산은 특권 명령이다.
CPU 보호
- CPU가 하나의 프로그램에 의해 독점되는 것을 막기 위해 타이머(timer)라는 하드웨어를 사용한다.
- 타이머 인터럽트 (timer interrupt)
- 타이머는 정해진 시간이 지나면 인터럽트를 발생시켜 운영체제가 CPU의 제어권을 획득할 수 있도록 한다.
- 인터럽트 처리루틴에서는 현재 실행 중인 프로그램으로부터 CPU를 빼앗아 다른 프로그램에게 CPU를 이양하는 작업을 수행한다.
- 타이머는 일정한 시간 단위로 설정될 수 있고, 매 clock tick 마다 1씩 감소하여 타이머가 0이 되는 순간 인터럽트를 발생시킨다.
- 타이머의 값을 설정하는 명령을 load timer 라고 하며, 이는 특권 명령이다.
- 시분할 시스템(= 여러 프로그램이 CPU의 시간을 조금씩 나누어 사용하는 시스템; 대부분의 컴퓨터)에서 현재 시간을 계산하기 위해서도 사용된다.
(정리) 사용자 프로그램에서 입출력 요청을 하는 경우
- 운영체제에게 system call(소프트웨어 인터럽트)로 입출력 작업을 요청한다.
트랩(trap)이 발생하여 CPU의 제어권이 운영체제로 넘어가게 되고, 인터럽트 벡터의 특정 위치를 통해 해당 인터럽트 처리루틴으로 이동하여 명령을 수행한다. (ex. 디스크 컨트롤러에게 입출력 요청 수행 명령)
인터럽트 하드웨어에 의해 모드 비트가
0
으로 설정되어 운영체제가 입출력을 수행할 수 있게 된다.요청된 입출력이 완료되면 컨트롤러가 CPU에게 인터럽트(하드웨어 인터럽트)를 통해 알리고, CPU의 제어권이 다시 사용자 프로그램에 넘어간다.
사용자 프로그램에게 CPU 제어권이 넘어갈 때 모드 비트가
1
로 설정된다.- 사용자 프로그램이 다시 CPU를 할당 받으면 system call 이후의 명령을 수행할 수 있다.
References
- “운영체제와 정보기술의 원리(반효경 저)”, 3장 컴퓨터 시스템의 동작 원리
- https://www.cs.csustan.edu/~john/Classes/Previous_Semesters/CS3750_OperatingSys_I/2019_02_Spr/Notes/Chap09/09_MainMemory.html