컴퓨터 시스템의 동작 원리

DEVJUN·2022년 7월 8일
0

운영체제(OS)

목록 보기
2/5
post-thumbnail

1. 컴퓨터 시스템의 구조🖥

  컴퓨터 시스템의 구조는 컴퓨터 내부장치인 CPU, 메모리와 컴퓨터 외부 장치인 디스크, 키보드, 마우스, 모니터, 네트워크 장치 등으로 구성된다. 컴퓨터는 외부장치에서 내부장치로 데이터를 읽어와 각종 연산을 수행하고, 결과를 외부장치로 내보내는 방식으로 동작하는데 이때 데이터가 들어오는 것을 입력(input), 외부장치로 데이터가 나가는 것을 출력(output)이라고 한다. 따라서 컴퓨터 외부장치를 입출력 장치라고도 부른다.

  메모리 및 입출력장치 등의 각 하드웨어 장치에는 컨트롤러라는 것이 붙어 있는데 이는 일종의 작은 CPU로서, 컴퓨터 전체에 CPU라는 중앙 처리장치가 있듯이 컨트롤러는 각 하드웨어 장치마다 존재하면서 이들을 제어하는 CPU라고 할 수 있다.🖥

  ✍🏻운영체제는 컴퓨터가 부팅되었을 때부터 항상 수행되면서 각종 자원들을 관리해야 하므로 항상 메모리에 올라가 있다.❗️ 하지만 운영체제의 모든 코드를 다 메모리에 올리면 메모리 낭비가 발생하므로 운영체제 중 항상 메모리에 올라가 있는 부분은 전체 운영체제 중 핵심적인 부분에 한정되며, 이 부분을 커널(Kernel)❗️이라고 한다.


2. CPU 연산과 I/O 연산🔡

  ➡️ 🖥컴퓨터에서 연산을 한다는 것은 CPU가 무언가 일을 한다는 뜻이다.
입출력 장치들의 I/O 연산은 입출력 컨트롤러가 담당하고, 컴퓨터 내에서 수행되는 연산은 메인 CPU가 담당한다. 이때 입출력 장치와 메인 CPU는 동시 수행이 가능🤔하다.

  각 장치마다 장치를 제어하기 위해 설치된 장치 컨트롤러는 장치로부터 들어오고 나가는 데이터를 임시로 저장하기 위한 작은 메모리를 가지고 있다. 이를 로컬버퍼(local buffer)라고 부른다.

  예를 들어 프로그램 B가 수행중에 디스크에서 데이터를 읽어오라는 명령을 내리면, 디스크 컨트롤러가 물리적인 디스크에서 내용을 읽어 이를 로컬버퍼에 저장한다.

  원하는 데이터를 다 읽어오고 나면 B는 자신이 필요로 하는 데이터를 다 읽어 왔으므로 메인 CPU에서 다음 일을 수행할 수 있다. 이때 로컬버퍼로 읽어오는 작업이 끝났는지를 메인 CPU가 지속적으로 체크하는 것이 아니라 장치에 있는 💥컨트롤러가 인터럽트❗️를 발생시켜 CPU에 보고⭐️하게 된다.

  인터럽트란 컨트롤러들이 CPU의 서비스가 필요할 때 이를 통보하는 방법을 말한다. 기본적으로 CPU는 매 시점 메모리에서 명령을 하나씩 읽어와서 수행한다. 이때 CPU 옆에는 인터럽트 라인(interrupt line)이라는 것이 있는데 CPU가 자신의 작업을 하던 중간에 인터럽트 라인에 신호가 들어오면 하던 일을 멈추고 인트럽트와 관련된 일을 먼저 처리한다.


3. 인터럽트의 일반적 기능

  운영체제 커널 내에는 인터럽트가 들어왔을 때 해야 할 일이 미리 개발자들로부터 프로그래밍되어 코드가 보관되어 있다.

  인터럽트에는 하드웨어 인터럽트소프트웨어 인터럽트가 있다. CPU의 서비스가 필요한 경우 인터럽트 라인에 신호를 보내 인터럽트가 발생했음을 알리는 것은 동일하지만 하드웨어 인터럽트는 컨트롤러 등 하드웨어 장치가 CPU의 인터럽트 라인을 세팅하는 반면,  소프트웨어 인터럽트는 소프트웨어가 그 일을 수행한다는 차이가 있다.

  운영체제는 할 일을 쉽게 찾아가기 위해 인터럽트 벡터(interrupt vector)를 가지고 있다. 이는 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야 할 코드가 위치한 부분을 가리키고 있는 자료구조를 말한다. 또한 인터럽트 처리 후 돌아갈 위치를 알아야 하므로 인터럽트 처리 전에 수행 중이던 작업이 무엇이었는지 반드시 저장해두어야 한다.

  소프트웨어의 인트럽트의 예로는 예외상황(exception)시스템 콜(system call)이 있다.

  1️⃣예외 상황이란 사용자 프로그램이 0으로 나누는 연산 등 비정상적인 작업을 시도하거나, 자신의 메모리 영역 바깥에 접근하려는 시도 등 권한이 없는 작업을 시도할 때 이에 대한 처리를 위해 발생시키는 인터럽트를 말한다.

  2️⃣시스템 콜이란 사용자 프로그램이 운영체제 내부에 정의된 코드를 실행하고 싶을 때 운영체제에 서비스를 요청하는 방법이라고 볼 수 있다.

  사용자 프로그램 자신의 코드는 직접 CPU를 가지고 실행하지만, 사용자 프로그램에 정의되지 않고 운영체제 커널에 있는 코드를 사용자 프로그램이 실행하고자 할 때에는 인터럽트 라인 세팅을 통해 CPU 제어권을 운여체제로 넘겨 실행하게 되는 것이다. 예를 들어 애플리케이션 개발자가 프로그램 작성 중 키보드 입력이나 화면 출력 등의 입출력 작업이 필요한 경우 본인이 입출력을 수행하는 코드를 작성하는 것이 아니라 이미 존재하는 커널의 코드를 호출해서 처리한다.


4. 인터럽트 핸들링🥌

  인터럽트 핸들링(interrupt handling)이란 인터럽트가 발생한 경우에 처리해야 할 일의 절차를 의미한다.

  프로그램 A가 실행되고 있을 때 인터럽트가 발생하면 A의 현재 상태를 먼저 저장해야 인터럽트 관련된 일을 처리한 후 다시 하던 일로 돌아올 수 있다.

  운영체제는 현재 시스템 내에서 실행되는 프로그램들을 관리하기 위해 프로세스 제어블록(Process Control Block: PCB)🧱라는 자료구조를 둔다. PCB는 각각의 프로그램마다 하나씩 존재하며 해당 프로그램의 어느 부분이 실행 중이었는지를 저장하고 있다.

  오늘날의 컴퓨터에서 운영체제는 인터럽트가 발생할 때에만 실행된다. 이는 시스템이 부팅 후 정상 상태에 머무르게 되면 CPU가 항상 사용자 프로그램에 의해 사용되며, 운영체제는 단지 인터럽트가 발생했을 때에만 잠깐 CPU의 제어권을 획득할 수 있기 때문이다. 그럼에도 불구하고 운영체제는 컴퓨터 시스템 내의 모든 하드웨어 및 소프트웨어 자원을 체계적이고 효율적으로 관리할 수 있다.


5. 입출력 구조

  입출력 방식에는 동기식 입출력비동기식 입출력이 있다.

  동기식 입출력은 입출력이 진행되는 동안 그 프로그램의 다음 명령을 수행하지 않고 기다린다. 그러다가 입출력이 완료되어 인터럽트를 통해 그 사실이 전달된 후에야 CPU의 제어권🎮이 그 프로그램에게 넘어가서 다음 명령을 수행할 수 있게 된다.

  동기식 입출력은 입출력이 완료될 때까지 다음 명령을 수행할 수 없기 때문에 CPU가 낭비된다. 또한 다른 프로그램에게 CPU를 양도하는 방법을 사용하지 않고 입출력 연산이 완료될 때까지 기다린다면, 매 시점 하나의 입출력 연산만이 일어날 수 있다. 그러나 CPU의 효율적인 사용을 위해 입출력이 수행되는 동안 다른 프로그램에게 CPU를 양도하면 동시에 다수의 입출력 연산이 일어날 수 있다.

  이와 같이 다수의 프로그램이 동시에 입출력 연산을 요청하는 경우 동기성(synchronization)을 보장하기 위해 장치마다 큐(queue)를 두어 요청된 순서대로 처리할 수 있도록 한다.

  장치마다 큐 헤더가 존재하고 각 장치별로 입출력 수행 순서를 지켜주기 위한 큐를 관리하고 있다. 입출력이 완료될 때까지 아무일도 못하는 것이 아니라, 입출력과 관련없는 프로그램을 수행하도록 하고, 요청된 입출력 연산이 완료되면 CPU에게 입출력이 완료되었음을 알려주는 방식으로 진행된다.

  비동기식 입출력은 입출력 연산을 요청한 후에 연산이 끝나기를 기다리는 것이 아니라 CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 곧바로 다시 부여하는 방식을 말한다.

  사진에서 1️⃣ 동기식 입출력에서는 사용자가 I/O 요청을 하면 먼저 운영체제의 커널로 CPU의 제어권이 넘어와서 입출력 처리와 관련된 커널의 코드가 수행되고 이때 입출력을 호출한 프로세스의 상태를 봉쇄 상태로 바꾸어 입출력이 완료될 때까지 CPU를 할당받지 못하도록 하고, 입출력이 완료되면 I/O 컨트롤러가 CPU에게 인트럽트를 발생시켜 입출력이 완됴되었음을 알려주고 나서야 프로세스의 봉쇄 상태를 해제 시켜 CPU를 할당 받을수 있는 권한이 다시 생기는 것이다.

  2️⃣ 비동기식 입출력에서는 CPU의 제어권이 입출력을 요청한 프로세스에게 곧바로 주어지며, 입출력 연산이 완료되는 것과 무관하게 처리 가능한 작업부터 처리한다.

6. DMA

  원칙적으로 메모리는 CPU에 의해서만 접근할 수 있다. 모든 메모리 접근 연산이 CPU에 의해서만 이루어질 경우 입출력 장치가 메모리 접근을 원할 때마다 인터럽트에 의해 CPU업무가 방해를 받게 되어 CPU 사용의 효율성이 떨어지는 문제점이 발생하게 된다.

  이를 극복하기 위해 CPU 이외에 메모리 접근이 가능한 장치를 하나 더 두는 경우가 있는데, 이와 같은 장치를 DMA(Direct Memory Access)라고 부른다. DMA는 일종의 컨트롤러로서, CPU가 입출력 장치들의 메모리 접근 요청에 의해 자주 인트럽트 당하는 것을 막아주는 역할을 한다.

  DMA를 사용하게 되면 로컬버퍼에서 메모리로 읽어오는 작업을 CPU가 담당하는 것이 아니라 DMA가 대행함으로써 CPU는 원래 하던 작업을 멈추고 인터럽트를 처리할 필요가 없어지는 것이다. 이를 통해 CPU에 발생하는 인터럽트의 빈도를 줄여 CPU를 좀 더 효율적으로 관리하고 입출력 연산을 빠르게 수행할 수 있게 되는 것이다.

7. 💽저장장치의 구조

  컴퓨터 시스템을 구성하는 저장장치는 주기억장치와 보조기억장치로 나누어진다.

  주기억장치는 보통 메모리라고 부르며 전원이 나가면 저장되었던 내용이 모두 사라져버리는 휘발성(volatile)의 RAM을 매체로 사용하는 경우가 대부분이다.

  보조기억장치는 전원이 나가도 저장된 내용을 기억할 수 있는 비휘발성(nonvolatile)의 마그네틱 디스크를 주로 사용한다.

8. 저장장치의 계층 구조

  컴퓨터 시스템을 구성하는 저장장치는 빠른 저장장치부터 느린 저장장치까지 단계적인 계층 구조로 이루어진다. 빠른 저장장치는 단위 공간당 가격이 높기 때문에 적은 용량을 사용하고, 느린 저장장치는 가격이 저렴해 대용량을 사용하지만 접근 속도가 느리다.

  저장장치 계층은 최상위의 CPU 내부에 존재하는 레지스터(register)부터 캐시 메모리(cache memory), 메인 메모리(main memory)등의 휘발성 저장장치로 구성되는 부분이 상위에 존재하며 이부분에 저장되는 정보는 전원이 나가면 그 내용이 사라진다. 반면 메인 메모리보다 아랫부분을 구성하는 저장장치 계층은 전원이 나가도 지워지지 않는 비휘발성 저장장치이다.

  상위 저장장치 계층으로 갈수록 접근속도는 빠르지만 용량은 적다. 하지만 당장 필요한 정보만을 선별적으로 저장하면 하위에 있는 큰 용량의 저장장치를 가지고 있는 것과 비슷한 성능 효과를 낼수 있다.

  그림에서 레지스터와 메인 메모리 사이에 존재하는 캐시 메모리로 여러가지 캐싱 기법을 이용해 적은 용량의 캐시 메모리를 사용해서 메인 메모리와 같이 큰 용량을 가진 것처럼 효율적으로 동작하도록 관리할 수 있다.

  캐싱 기법은 상대적으로 느린 저장장치에 있는 내용 중 당장 사용되거나 빈번히 사용될 정보를 빠른 저장장치에 선별적으로 저장함으로써 두 저장장치 사이의 속도를 완충 시킨다.

  캐싱 기법이 적은 용량으로도 효과를 거둘 수 있는 것은 컴퓨터 내의 데이터나 프로그램을 구성하는 모든 부분이 균일하게 사용되는 것이 아니라 일부분만이 집중적으로 사용되고 특정 부분은 거의 사용되지 않기 때문❗️이다. 예를 들어 프로그램 코드 중에서 많은 횟수 동안 반복되는 코드와, 한번 수행되고 끝나는 코드가 있을 수 있는데 반복되는 코드를 빠른 저장장치에 올려놓으면 적은 저장공간만으로도 전체 시스템의 평균적인 성능을 향상시킬 수 있다.

9. 하드웨어의 보안

  운영체제는 여러 프로그램이 동시에 실행될 수 있는 다중 프로그래밍 환경에서 동작하기 때문에 각 프로그램이 다른 프로그램의 실행을 방해하거나 프로그램 간에 충돌을 일으키는 문제를 막기 위해 하드웨어에 대한 보안 기법이 필요하다.

  하드웨어적인 보안을 유지하기 위해서 운영체제는 커널모드(kernel mode, system mode)사용자모드(user mode) 이 두가지 모드를 지원한다.

  커널모드는 운영체제가 CPU의 제어권을 가지고 운영체제 코드를 실행하는 모드로서, 이 모드에서는 모든 종류의 명령을 다 실행할 수 있다. 또한 중요한 정보에 접근해 위험한 상황을 처리할 수 있는 연산은 커널 모드에서만 실행되도록 하여 일반 사용자 프로그램이 직접 위험한 명령을 수행할 수 없도록 한다.

  사용자모드는 일반 사용자 프로그램이 실행되며 제한적인 명령만 수행할 수 있게 한다.

  사용자 프로그램이 CPU를 가지고 있는 동안에는 운영체제 자신의 코드를 실행하지 못하도록 사용자 프로그램을 감시한다. 컴퓨터 시스템은 CPU 내부에 모드비트(mode bit)를 두어 사용자 프로그램을 감시하게 된다. 모드비트가 0으로 세팅되어 있으면 커널모드로서 모든 명령을 수행할 수 있고, 모드 비트가 1로 세팅되어 있으면 사용자 모드로서 제한된 명령만을 수행할 수 있다.

  사용자 프로그램이 수행되다가 하드웨어 접근 등 보안에 필요한 중요한 명령을 수행해야 할 경우에는 시스템 콜을 통해 운영체제가 대신해줄 것을 요청한다. 그러면 CPU의 제어권은 다시 운영체제로 넘어가게 된다.

  사용자 프로그램이 디스크에 저장된 파일에 자유롭게 접근할 수 있다면 보안상 문제가 발생할 수 있다. 자신의 소유가 아닌 다른 사람의 파일에 접근할 수 있기 때문이다. 그래서 모든 입출력 명령은 특권명령(시스템 보안과 관련된 명령)으로 규정해 사용자 프로그램이 직접 입출력을 하는 것을 차단한다.

  그리고 입출력이 필요할 때에는 운영체제에 요청하여 운영체제가 입출력 명령을 대신 수행하게 한다. 입출력은 특권명령이기 때문에 모드비트가 0일 때에만 수행할 수 있으며, 사용자 프로그램이 입출력을 하고 싶으면 시스템 콜로 운영체제에 요청해야 한다.

10. 메모리 보안

  여러 프로그램이 메모리에 동시에 올라가서 실행되어 하나의 사용자 프로그램이 다른 사용자 프로그램이나 운영체제가 위치한 메모리 영역을 침범할 수 있기 때문에 메모리의 경우에도 보안이 필요하다.

  예를 들어 하나의 사용자 프로그램이 C언어의 포인터 등 메모리 주소 참조 연산을 잘못 사용해 다른 사용자 프로그램의 메모리 영역이나 운영체제 커널이 위치한 영역을 참조하려는 시도를 할 수 있다. 따라서 인터럽트 벡터나 인터럽트 처리루틴이 있는 곳은 보안이 필요하다.

  이러한 문제를 해결하기 위해 2개의 레지스터를 사용해서 프로그램이 접근하려는 메모리 부분이 합법적인지 체크함으로써 메모리를 보호할 수 있다. 이때 사용되는 2개의 레지스터는 기준 레지스터한계 레지스터이다.

  기준 레지스터는 어떤 프로그램이 수행되는 동안 그 프로그램이 합법적으로 접근할 수 있는 메모리상의 가장 작은 주소를 보관하고 있고, 한계 레지스터는 그 프로그램이 기준 레지스터값부터 접근할 수 있는 메모리의 범위를 보관하고 있다.

  사용자 프로그램은 기준 레지스터에 있는 주소부터 기준 레지스터 + 한계 레지스터값 사이의 주소 영역에만 접근할 수 있으며, 접근하려는 주소가 이 범위 안에 없으면 불법적인 메모리 접근이므로 예외상황이라는 일종의 소프트웨어적인 인터럽트가 발생하게 된다.

  이러한 예외상황은 운영체제에 소프트웨어 인터럽트를 발생시켜 CPU의 제어권을 해당 프로그램으로부터 운영체제로 이양시키고, 운영체제는 예외상황을 발생시킨 프로그램을 강제 종료시킨다.

  사용자모드인 경우에는 기준 레지스터와 한계 레지스터를 사용해서 메모리를 보호하게 되고, 커널모드에서는 메모리에 무제한으로 접근하는 것이 가능하다.

  메모리 접근 명령은 특권명령이 아니지만, 올바르지 않은 접근 시도로부터 메모리를 보호하기 위해서는 기준 레지스터와 한계 레지스터의 값을 세팅하는 연산은 특권명령으로 규정해야 한다.

11. CPU 보호😷

  CPU는 컴퓨터 시스템 내에 하나만 존재한다.

  CPU를 특정 프로그램이 독점하는 것을 막기위해 운영체제는 ⏰타이머(timer)라는 하드웨어를 사용한다. 타이머는 정해진 시간이 지나면 인터럽트를 발생시켜 운영체제가 CPU의 제어권을 획득할 수 있도록 하는 역할을 수행한다.

  타이머는 일정한 시간 단위로 세팅될 수 있으며 매 클럭 틱 때마다 1씩 감소하고 타이머가 0이되는 순간 인터럽트가 발생한다.

12. 시스템 콜을 이용한 입출력 수행

  사용자 프로그램이 디스크의 파일에 데이터를 쓰거나 읽어오는 행위, 키보드로부터 입력을 받거나 수행 결과를 화면에 출력하는 행위 등은 모두 특권명령인 입출력 명령에 해당하므로 사용자 프로그램이 직접 수행할 수 없다.

  입출력 명령은 운영체제 코드에 구현되어 있으며, 사용자 프로그램이 직접 입출력을 수행하는 대신 운영체제에게 📞시스템 콜이라는 서비스 대행 요청을 하여 입출력을 수행한다.

  시스템 콜은 일종의 소프트웨어적인 인터럽트로서 사용자 프로그램이 시스템 콜을 할 경우 트랩이 발생해 💥CPU의 제어권⭐️이 운영체제로 넘어가게 된다.

  예를 들어 시스템 콜이 입출력 요청이었으면 디스크 컨트롤러에게 입출력 요청을 수행하도록 명령하고, 추후에 디스크 컨트롤러가 입출력 수행을 마치면 CPU에게 인터럽트를 발생시켜 입출력이 완료되었음을 알려줌으로써 해당 프로그램이 다시 CPU를 할당 받을 수 있도록 한다.

profile
🧑🏻‍💻iOS

2개의 댓글

comment-user-thumbnail
2022년 7월 8일

유익한 글 잘 읽고갑니다~!

1개의 답글