[운영체제] 컴퓨터의 구조와 성능

Doyeon Lim·2022년 1월 12일
0

운영체제

목록 보기
2/3
post-thumbnail

> Tech-I-Learned Github 바로가기

쉽게 배우는 운영체제를 읽고 스스로 이해하기 위해 정리한 내용입니다.

📗컴퓨터의 구성

컴퓨터는 중앙처리장치(CPU), 메인메모리, 입력장치, 출력장치, 저장장치로 구성되어 있다.

폰노이만 구조

폰노이만 구조는 CPU, 메모리, 입출력장치, 저장장치가 *버스로 연결되어 있는 구조를 말한다.

*버스 : 각 장치를 연결하는 선의 집합이자 데이터가 지나다니는 통로

미국의 수학자 존 폰노이만은 메모리를 이용해 프로그래밍이 가능하도록 하드웨어는 그대로 둔 채 작업을 위한 프로그램만 교체해 메모리에 올리는 방식을 제안했다. 따라서 이 구조에서 가장 중요한 특징은 다음과 같다.

모든 프로그램은 메모리에 올라와야 실행할 수 있다.

✅CPU의 구성과 동작

CPU의 구성

CPU는 산술논리 연산장치, 제어장치, 레지스터로 구성되어 있다.

1. 산술논리 연산장치
산술논리 연산장치 Arithmetic and Logic Unit는 데이터의 산술 연산과 논리 연산을 수행한다.

2. 제어장치
제어장치 control unit는 작업을 지시하는 역할을 한다.

3. 레지스터
레지스터 register는 CPU 내에서 데이터를 임시로 보관하는 공간이다.

  • 사용자 가시 레지스터 user-visible register
    • 데이터 레지스터 data register : 메모리에서 가져온 데이터를 임시로 보관하는 공간으로, 일반 레지스터 또는 범용 레지스터라고 부른다.
    • 주소 레지스터 address register : 데이터 또는 명령어가 저장된 메모리의 주소가 저장되는 공간이다.
  • 특수 레지스터 user-invisible register
    • 프로그램 카운터 program counter : 다음에 실행할 명령어의 주소를 기억하고 있다가 제어장치에 알려주는 역할을 하며, 명령어 포인터라고도 한다.
    • 명령어 레지스터 instruction register : 현재 실행 중인 명령어를 저장한다.
    • 메모리 주소 레지스터 memory address register : 메모리에서 데이터를 가져오가나 메모리로 데이터를 보낼 때 주소를 지정하기 위해 사용한다.
    • 메모리 버퍼 레지스터 memory buffer register : 메모리에서 가져온 데이터나 메모리로 옮겨 갈 데이터를 임시로 저장하며 항상 MAR과 함께 동작한다.
  • 기타
    • 프로그램 상태 레지스터 program status register : 산술논리 연산장치와 연결되어 연산 결과가 양수/음수/0인지 또는 자리 올림 유무 등을 저장하며, 플래그 레지스터/상태 레지스터/컨디션 레지스터라고도 부른다.

버스의 종류

버스는 CPU와 메모리, 주변장치 간에 데이터를 주고받을 때 사용한다.

시스템 버스 system bus는 메모리와 주변장치를 연결하는 버스로 전면 버스 Front-Side Bus라고 한다.

1. 제어 버스 control bus

  • 다음에 어떤 작업을 할지 지시하는 제어 신호가 양방향으로 오고 간다.

2. 주소 버스

  • 데이터를 읽거나 쓸 때 어느 위치에서 작업할 것인지를 알려주는 위치 정보(주소)가 단방향으로 오고 가며, 메모리 주소 레지스터와 연결되어 있다.

3. 데이터 버스

  • 제어 버스가 다음 작업을 지시하는 신호를 보내고 주소 버스가 정보를 전달하면 데이터 버스가 데이터를 이동시킨다. 메모리 버퍼 레지스터와 연결되어 있으며 데이터 이동이 양방향으로 이루어진다.

후면 버스 Back-Side Bus는 CPU 내부 버스로, CPU 내부에 있는 장치를 연결한다.

✅메모리의 종류

메모리는 읽고 쓸 수 있는 램 Random Access Memory과 읽기만 가능한 롬 Read Only Memory로 구분된다.

1. 램 RAM

  • 휘발성 메모리 volatility memory : 전력이 끊기면 데이터가 사라진다.
    • DRAM Dynamic RAM : 저장된 데이터가 일정 시간이 지나면 사라지기 때문에 재생이 필요하다. 일반적으로 메인메모리에 사용한다.
    • SRAM Static RAM : 전력이 공급되는 동안에는 데이터를 보관할 수 있어 재생할 필요가 없다. 속도는 빠르지만 가격이 비싸며, 일반적으로 캐시같은 고속메모리에 사용한다.
    • SDRAM Synchronous DRAM : DRAM이 발전된 형태로 클록틱(펄스)이 발생할 때마다 데이터를 저장하는 동기 DRAM이다.
  • 비휘발성 메모리 non-volatility memory : 전력이 끊겨도 데이터를 보관할 수 있다.
    • 플래시 메모리 flash memory : 디지털카메라, mp3 플레이어, usb 드라이버같이 전력이 없어도 데이터를 보관하는 저장장치로 많이 사용된다. 다만 오래 사용하면 성능이 저하되거나 데이터를 잃어버릴 수 있으니 주의해야 한다.
    • SSD : 가격이 비싸지만 빠른 데이터 접근 속도, 저전력, 내구성 때문에 많은 기기에 사용된다.

*휘발성 메모리는 메모리 내부가 복잡하고 속도가 느리며 가격이 비싸기 때문에 아직도 메인메모리는 휘발성 메모리를 사용하고 있다.

2. 롬 ROM

  • 마스크 롬 mask ROM : 데이터를 지우거나 쓸 수 없다.
  • PROM Programmable Rom : 전용 기계를 이용해 데이터를 한 번만 저장할 수 있다.
  • EPROM Erasable PROM : 데이터를 여러 번 쓰고 지울 수 있다. 플래시 메모리처럼 사용할 수 있지만 가격이 비싸서 잘 사용하지 않는다.

*롬은 전력이 끊겨도 데이터를 보관하는 것이 장점이지만 데이터를 한 번 저장하면 바꿀 수 없는 특성이 있기때문에 바이오스를 롬에 저장한다.

메모리 보호

CPU는 현재 진행 중인 작업의 메모리 시작 주소를 경계 레지스터에 저장한 후 작업을 하고, 해당 작업이 차지하는 메모리의 크기(마지막 주소)를 한계 레지스터에 저장한다.

사용자의 작업이 진행되는 동안 두 레지스터 주소 범위를 벗어나는지 하드웨어적으로 점검함으로써 메모리를 보호한다.

주소 범위를 벗어나 메모리 오류 관련 인터럽트가 발생하면 모든 작업이 중단되고 cpu는 운영체제가 인터럽트를 처리하도록 한다. 운영체제는 해당 프로그램을 강제 종료시킨다.

부팅

프로그램이 실행되려면 반드시 메모리에 올려야하는데, 그렇다면 운영체제는 누가 메모리에 올리는 것일까?

부팅 bootiong컴퓨터를 켰을 때 운영체제를 메모리에 올리는 과정이다.

사용자가 전원을 키면 롬에 저장된 바이오스가 실행되고 주요 하드웨어가 제대로 작동하는지 확인한다.

이상이 없다면 하드디스크의 첫 번째 섹터인 마스터 부트 레코드에 저장된 부트스트랩을 메모리에 가져와 실행한다.

부트스트랩은 운영체제를 실행하기 위한 코드이며, 메모리에 올라오면 하드디스크에 저장된 운영체제를 메모리에 불러온다.

📘컴퓨터의 성능

cpu 내부 버스의 속도가 시스템 버스의 속도보다 빠르기 때문에 메모리를 비롯한 주변장치의 속도가 cpu의 속도를 따라가지 못한다. 따라서 주변 장치 간 속도 차이를 개선하고 시스템 작업 속도를 올려야 한다.

✅버퍼

버퍼 buffer는 속도에 차이가 있는 두 장치 사이에서 그 차이를 완화하는 역할을 하기 위해, 일정량의 데이터를 모아 옮긴다.

스풀 Simultaneous Peripheral Operation On-Linecpu와 입출력장치가 독립적으로 동작하도록 고안된 소프트웨어적인 버퍼로, 대표적인 예는 프린터에 사용되는 스풀러이다. 스풀러는 한 인쇄물이 완료될 때까지 다른 인쇄물이 끼어들 수 없으므로 프로그램 간에 배타적이다.

✅캐시

캐시 cache 메모리와 cpu 간의 속도 차이를 완화하기 위해 메모리의 데이터를 미리 가져와 저장해두는 임시 장소이다.

캐시는 버퍼의 일종으로, 사용될 것으로 예상되는 데이터를 미리 가져다 놓는 작업prefetch라고 한다.

캐시는 cpu 내부에 위치하고 FSB의 속도로 작동하며, cpu는 메모리에 접근해야 할 때 캐시를 먼저 방문하여 원하는 데이터가 있는지 찾아본다. 캐시에 해당 데이터가 있다면 캐시 히트 cache hit라고 하며, 캐시에 없어 메모리에서 데이터를 찾는다면 캐시 미스 cache miss라고 한다. 캐시 히트의 비율을 캐시 적중률 cache hit ratio라고 하며, 일반적인 컴퓨터의 캐시 적중률은 약 90%이다.

컴퓨터의 성능을 향상시키려면 캐시 적중률을 높여야하는데, 그 방법 중 하나는 캐시의 크기를 늘리는 것이다. 가격이 비싸기 때문에 크기를 늘리는 데 한계가 있어 몇 메가바이트 정도만 사용한다.

또다른 방법은 앞으로 많이 사용될 데이터를 가져오는 것으로, 현재 위치에 가까운 데이터가 멀리 있는 것보다 사용될 확률이 더 높다는 지역성 locality 이론이 있다.

캐시와 메모리

캐시의 데이터가 변경되면 메모리에 있는 원래 데이터를 변경해야 한다.

1. 즉시 쓰기 write through
캐시가 있는 데이터가 변경되면 이를 즉시 메모리에 반영한다. 빈번한 데이터 전송으로 성능이 느려진다는 단점이 있지만 항상 메모리 최신값이 유지되기 때문에 급작스러운 정전에도 데이터를 잃어버리지 않는다.

2. 지연 쓰기 write back
캐시의 변경된 내용을 모아서 주기적으로 반영하는 방식으로, 카피백 copy back이라고도 한다. 시스템 성능을 향상할 수 있으나 메모리와 캐시된 데이터 사이의 불일치가 발생할 수도 있다는 단점이 있다.

레벨별 캐시

캐시는 명령어와 데이터의 구분 없이 모든 자료를 가져오는 일반 캐시, 명령어와 데이터를 구분하여 가져오는 특수 캐시의 두 가지 레벨로 구분된다.

명령어 캐시는 명령어 레지스터와, 데이터 캐시는 데이터 레지스터와 연결되어 있다.
두 캐시는 CPU 레지스터에 직접 연결되기 때문에 L1 캐시라고 부르며, 일반 캐시는 메모리와 연결되기 때문에 L2 캐시라고 부른다.

✅저장장치 계층 구조

좋은 성능을 가진 컴퓨터를 구성하려면 상당한 비용을 지불해야한다.

가격과 성능 사이의 타협점으로 저장장치의 계층 구조 storage hierarchy가 존재한다. 속도가 빠르고 값이 비싼 저장장치는 cpu 가까운 쪽에, 값이 싸고 용량이 큰 저장장치는 반대쪽에 배치해 적당한 가격으로 빠른 속도와 큰 용량을 얻을 수 있다.

✅인터럽트

초기의 컴퓨터는 cpu가 직접 입출력장치에서 데이터를 가져오거나 내보내는 폴링 polling 방식을 사용했다. cpu가 입출력장치의 상태를 주기적으로 검사해 일정 조건을 만족할 때 데이터를 처리하게 되면서 작업 효율이 떨어지게 되었다.

이 문제를 해결하기 위해 인터럽트 interrupt 방식을 사용해 cpu 작업과 저장장치의 데이터 이동을 독립적으로 운영하여 시스템의 효율을 높였다. 인터럽트는 입출력 관리자가 cpu에 보내는 완료 신호이다.

인터럽트 방식 동작 과정

인터럽트 방식의 동작 과정은 다음과 같다.

[인터럽트 방식의 동작 과정]
1. cpu가 입출력 관리자에게 입출력 명령을 보낸다.
2. 입출력 관리자는 데이터를 메모리에 가져다놓거나 메모리에 있는 데이터를 저장장치로 옮긴다.
3. 데이터 전송이 완료되면 입출력 관리자는 완료 신호(인터럽트)를 cpu에 보낸다.

인터럽트 방식에서는 어떤 주변장치의 작업이 끝났는지를 알리기 위해 장치의 고유 번호인 인터럽트 번호를 사용한다. 운영체제마다 다르며 윈도우의 경우 인터럽트 번호를 IRQ Interrupt ReQuest라고 부른다.

cpu가 여러 입출력 작업을 입출력 관리자에게 시킬 수 있으므로 여러 개의 인터럽트를 하나의 배열로 만든 인터럽트 벡트 interrupt vector를 사용한다.

입출력 외에도 강제 종료, 0으로 숫자를 나누는 경우 등에서도 인터럽트가 발생한다.

직접 메모리 접근 DMA

직접 메모리 접근 Direct Memory Access입출력 관리자가 cpu의 허락 없이 메모리에 접근할 수 있는 권한이다. DMA가 있어야 cpu의 관여없이 작업을 완료할 수 있다.

메모리 매핑 입출력

DMA를 사용하면 메모리에 CPU가 사용하는 데이터와 입출력 장치가 사용하는 데이터가 섞여있게 된다.

이를 막기 위해 CPU가 사용하는 메모리 공간과 DMA를 통해 출입이 가능한 데이터를 위한 공간을 분리하는 기법메모리 매핑 입출력 Memory Mapped I/O를 사용한다.

cycle stealing

CPU와 입출력 장치의 DMA가 동시에 메모리에 접근하려 한다면 보통 CPU가 메모리 사용 권한을 양보한다. 입출력장치의 속도가 느리기 때문에 양보하며, 이러한 상황을 사이클 훔치기 cycle stealing이라고 한다.

📒병렬 처리

CPU의 성능을 향상하는 가장 좋은 방법은 클록을 높이거나 캐시의 크기를 늘리는 것이지만 발열 문제와 비용 문제로 인해 다른 방법이 필요하다.

그 방법으로는 CPU의 핵심 기능을 가진 코어를 여러 개 만들거나, 동시에 실행 가능한 명령의 개수를 늘리는 것이 있다.

여기서 말한 동시에 여러 개의 명령을 처리하는 방식병렬 처리 parallel processing이라고 한다. 이 방식은 코어의 개수와 상관없이 작동 가능하다.

하나의 코어에 여러 개의 *스레드를 이용하는 방식인 파이프라인 기법 등이있다.

*스레드 Thread : cpu가 처리할 수 있는 작업의 단위, 여러 개의 스레드를 동시에 처리하는 방법을 멀티 스레드라고 한다.

✅병렬 처리 고려사항

  1. 상호 의존성이 없어야 병렬 처리가 가능하다.
    각 명령이 서로 독립적이고 앞의 결과가 뒤에 영향을 끼치지 않아야한다.

  2. 각 단계의 시간을 거의 일정하게 맞춰야 원만하게 이루어진다.
    각 단계의 처리 시간이 일정하지 않다면 가장 긴 시간이 걸리는 단계에서 병목 현상이 발생하며 전체 작업 시간이 늘어나게 된다.

  3. 전체 작업 시간을 몇 단계로 나눌지 고려해야한다.
    작업을 n개로 쪼갰을 때 n을 병렬 처리의 깊이 depth of parallel processing이라고 한다. 이는 동시에 처리할 수 있는 작업의 개수를 의미하며, 이 개수가 너무 많아지면 작업을 이동하고 새로운 작업을 불러오는 시간이 너무 많이 걸려 성능이 떨어질 수 있다. 보통은 병렬 처리의 깊이를 10~20 정도로 한다.

✅병렬 처리 기법

cpu 내에서 제어장치가 명령어를 가져와 해석한 후 실행하고 결과를 저장하는 과정을 하나의 스레드라고 한다. 이 스레드를 이루는 각 단계는 cpu의 클록과 연동되어 한 클록에 한 번씩 이루어진다.

cpu에서 명령어가 실행되는 과정은 다음과 같이 4단계로 나눌 수 있다.

[cpu 명령어 처리 단계]
1. 명령어 패치 Instruction Fetch : 다음에 실행할 명령어를 명령어 레지스터에 저장한다.
2. 명령어 해석 Instruction Decode : 명령어를 해석한다.
3. 실행 Execution : 해석한 결과를 토대로 명령어를 실행한다.
4. 쓰기 Write Back : 실행된 결과를 메모리에 저장한다.

*연구자 또는 책에 따라 다르게 나눈다.

병렬 처리 기법은 하나의 코어에서 작업을 나누어 처리하거나 여러 코어를 사용해 동시에 작업을 진행하는 등 다양한 방법이 있다.

파이프라인 기법

파이프라인 pipeline 기법cpu 사용을 극대화하기 위해 명령을 겹쳐서 실행하는 방법으로, 하나의 코어에 여러 개의 스레드를 사용하는 기법이다.

명령어를 여러 단계로 분할하고 각 단계를 동시에 처리하는 하드웨어를 독립적으로 구성하여, 각 단계가 쉬지 않고 명령어를 처리할 수 있게 된다.

파이프라인 기법의 여러 가지 문제를 파이프라인의 위험이라고 부르는데, 크게 데이터 위험, 제어 위험, 구조적 위험으로 구분된다.

[파이프라인의 위험]

1. 데이터 위험 data hazard
데이터의 의존성 때문에 발생하는 문제로, 뒤의 명령어에서 사용하는 데이터가 앞의 명령어에 의해 영향을 받는 경우에는 앞의 명령어가 끝날 때까지 동시에 실행되어서는 안 된다. 데이터 위험은 파이프라인의 명령어 단계를 지연하여 해결한다.

2. 제어 위험 control hazard
분기문이나 goto 문 같은 명령에서 발생하는 문제로, 프로그램의 카운터 값을 갑자기 변화시켜 발생한다. 해당 명령에서 순차적으로 실행되지 않다보니 현재 동시에 처리되고 있는 명령어들이 쓸모없어지게 된다. 이는 분기 예측이나 분기 지연 방법으로 해결한다.

3. 구조 위험 structural hazard
서로 다른 명령어가 같은 자원에 접근하려 할 때 발생하는 문제이다. 해결하기 어렵다고 알려져 있다.

슈퍼스칼라 기법

슈퍼스칼라 super-scalar 기법파이프라인을 처리할 수 있는 코어를 여러 개 구성해 복수의 명령어가 동시에 실행되도록 하는 방식이다. 이 방식 또한 처리되는 명령어가 상호 의존성 없이 독립적이어야 하며, 이를 위한 처리도 컴파일러에서 이루어지도록 조정해야한다. 대부분의 cpu가 이 기법을 사용하고 있다.

슈퍼파이프라인 기법

슈퍼파이프라인 spuer-pipeline 기법파이프라인 기법을 강화한 것으로, 한 클록마다 하나의 명령어를 실행하는 파이프라인 기법과 달리 파이프라인의 각 단계를 세분하여 한 클록 내에 여러 명령어를 처리할 수 있다. 빠른 시간 내에 다음 명령어가 시작될 수 있어 병렬 처리 능력이 높아진다. 이 기법은 크레이 슈퍼컴퓨터 cray super computer의 cpu에서 사용된다.

슈퍼파이프라인 슈퍼스칼라 기법

슈퍼파이프라인 슈퍼스칼라 super-pipelined super-scalar 기법앞의 병렬 처리 기법을 모두 합쳐 놓은 것이다.

VLIW 기법

VLIW Very Long Instruction Word 기법은 cpu가 병렬 처리를 지원하지 않을 경우 소프트웨어적으로 병렬 처리를 하는 방법이다. 이 기법에서는 동시에 수행할 수 있는 명령어들을 컴파일러가 추출하고 하나의 명령어로 압축하여 실행한다. 앞의 병렬 처리 기법들에 비해 동시에 처리하는 명령어의 개수가 적으며, 명령어 실행 시가 아닌 컴파일 시에 이루어진다.

📚정리

모든 프로그램은 메모리 위에 올라와야 실행할 수 있다.
cpu의 구성과 성능 향상을 위한 다양한 기법에 대해 이해할 필요가 있다.

profile
🙇‍♀️ Android

0개의 댓글