컴퓨터 시스템의 동작 원리 - 1

초보개발·2022년 2월 5일
0

OS

목록 보기
16/38
post-custom-banner

컴퓨터 시스템의 구조

컴퓨터 시스템은 CPU, 메모리와 디스크, 키보드, 마우스, 모니터, 네트워크 장치 등으로 구성되어 있다. 컴퓨터는 외부장치에서 내부장치로 데이터를 읽어와 각종 연산을 수행하고 그 결과를 외부장치로 다시 내보내는 방식으로 처리한다.

  • 디스크에서 내용을 읽어들여 컴퓨터 내부에서 연산을 수행한 후 디스크에 데이터를 저장했을 때에도 컴퓨터 입장에서는 입력과 출력이 발생했다고 볼 수 있다.

메모리 및 입출력장치 등 각 하드웨어 장치에 이 들을 제어하는 컨트롤러라는 일종의 작은 CPU가 달려있다.

  • 예) 디스크 제어: 디스크 컨트롤러, 메모리 제어: 메모리 컨트롤러

운영체제는 여러 프로그램이 동시에 충돌없이 수행될 수 있도록 하는 소프트웨어인데, 프로그램이 수행되려면 메모리에 적재되어 있어야 수행할 수 있다. 따라서 운영체제는 컴퓨터 부팅때 부터 메모리에 적재되어 꺼질 때까지 메모리에 올라가 있으며 각종 자원들을 관리한다. 하지만 운영체제의 모든 부분을 메모리에 적재시키게 되면 메모리 낭비기 때문에, 운영체제 중에서도 가장 핵심이 되는 부분만 항상 메모리에 올라가 있도록 하는데, 이 부분을 커널(kernel)이라고 부른다.

CPU 연산과 I/O 연산

컴퓨터의 연산: CPU가 어떤 일을 처리한다는 의미.
I/O 장치들의 I/O 연산은 입출력 컨트롤러가 담당하고 컴퓨터 내부의 연산들은 메인 CPU가 담당하여 처리한다. 이 때 입출력 장치와 메인 CPU는 동시 수행이 가능하다.

  • 프로그램 B가 CPU를 할당받아 수행 중이고, 프로그램 A는 하드디스크에서 정보를 읽어오는 작업을 수행하는 상황을 생각해보면, 두 가지 일은 다른 곳에서 발생하므로 동시에 수행될 수 있다.

각 장치마다 이를 제어하기 위해 설치된 장치 컨트롤러는 장치로부터 들어오고 나가는 데이터를 임시로 저장하기 위한 작은 메모리를 갖고 있는데 이 것을 로컬 버퍼(local buffer)라고 부른다. 디스크나 키보드에서 데이터를 읽어올 때 우선 로컬 버퍼에 임시로 저장한 후 메모리로 전달된다. 여기서 장치에서 로컬 버퍼로 읽어오는 일은 각 장치의 컨트롤러가 처리한다. 이 떄 로컬 버퍼로 읽어오는 작업이 완료되었는지를 메인 CPU에서 지속적으로 체크하지 않고 컨트롤러가 인터럽트를 발생시켜 CPU에 알려준다. 인터럽트(interrupt)는 컨트롤러들이 CPU의 서비스가 필요할 때 알려주는 신호를 말한다. CPU는 인스트럭션 하나를 끝낼 때마다 인터럽트가 발생했는지 체크한다.

  • 순서: 프로그램 데이터 요청 -> 디스크 컨트롤러가 로컬 버퍼에서 읽어옴 -> 인터럽트 발생 -> CPU가 인터럽트 체크 -> CPU는 하던 일을 저장하고 인터럽트 관련 업무 수행

인터럽트의 일반적 기능

운영체제 커널에는 인터럽트가 들어왔을 때 해야 할 일이 미리 프로그래밍되어 그 코드가 보관되어 있다. 커널 내에 있는 인터럽트 처리루틴(interrupt service routine)은 다양한 인터럽트에 대해 각각 처리해야 할 업무들을 정의하고 있다.

  • 앞의 예시 처럼 CPU는 인터럽트 발생시 수행하도록 미리 정의된 코드를 찾아서 수행한다. 수행하는 일은 디스크의 로컬 버퍼에 있는 내용을 사용자 프로그램의 메모리로 전달하고 해당 프로그램이 CPU를 할당받은 경우 다음 명령을 수행할 수 있음을 표시해두는 일이다.

할 일을 쉽게 찾아가기 위해 인터럽트 벡터(interrupt vector)를 갖고 있는데 이 것은 인터럽트 종류마다 번호를 정해 번호에 따라 처리해야 할 코드가 있는 부분을 가리키고 있는 자료구조를 말한다. 실제 처리해야할 코드는 인터럽트 처리루틴 또는 인터럽트 핸들러(interrupt handler)에 정의된다.
인터럽트 처리루틴을 통해서 해당하는 인터럽트 처리를 완료하고 나면 원래 수행하던 작업으로 돌아가서 일을 재개한다. 인터럽트 처리하고 나서 돌아갈 위치를 기억해야 하므로 인터럽트 수행 전 그 위치를 반드시 기억해 둬야한다.

  • 인터럽트 분류: 하드웨어 인터럽트, 소프트웨어 인터럽트(트랩, trap)
    인터럽트라 하면 하드웨어 인터럽트, 소프트웨어 인터럽트는 트랩이라고도 불린다. 방식은 동일하나 하드웨어 인터럽트는 컨트롤러 등 하드웨어 장치가 CPU의 interrupt line을 설정하고, 소프트웨어 인터럽트는 소프트웨어가 그 일을 수행한다는 차이점이 있다.

trap

exception과 system call이 대표적이다. 둘 다 모두 사용자 프로세스로부터 운영체제로 CPU 제어권이 넘어가서 처리된다. 이 때 프로그램 코드가 직접 인터럽트 라인을 세팅하는 명령을 실행해 인터럽트를 발생시키고 나서 제어권이 넘어가게 되므로 인터럽트로 포함된다.

  • exception: 사용자 프로그램이 0으로 나누는 연산과 같이 비정상적인 작업을 시도하려할 때 처리를 위해 발생시키는 인터럽트
  • system call: 사용자 프로그램이 운영체제 내부에 정의된 코드를 실행하고 싶을 때 운영체제에 서비스를 요청하는 방법

프로그램 코드는 직접 CPU를 할당받고 실행되지만 사용자 프로그램에 정의되지 않고 커널에 있는 코드를 사용자 프로그램이 실행하고자할 때에는 인터럽트 라인 설정을 통해서 CPU 제어권을 운영체제로 넘겨서 실행하게 된다.

  • 개발자가 프로그램 작성 중 키보드 입력이나 출력같이 입출력 작업이 필요할 때 개발자가 직접 IO 수행 코드를 작성하는게 아니라 커널에 이미 있는 코드를 호출해서 처리한다.

인터럽트 핸들링(interrupt handling)

인터럽트가 발생했을 때 처리해야 할 일의 절차를 의미한다.
프로그램 A가 실행중에 인터럽트가 발생하면 프로그램 A의 현재 상태(CPU에서 실행중인 명령의 메모리 주소 등을 포함한 부가적인 정보)를 먼저 저장한다. CPU에서 명령이 실행될 때 내부의 임시 기억장치인 레지스터에 데이터를 읽거나 쓰면서 작업을 하는데, 이때 인터럽트가 발생해 새로운 명령을 실행하면 기존의 레지스터값이 지워지게 된다. 그래서 CPU 내부에 이러한 상태를 저장해 두어야한다.
운영체제는 현재 실행되고 있는 프로그램들을 관리하기 위해 PCB(Process Control Block)라는 자료구조를 갖고 있다. 각각의 프로세스마다 PCB를 가지고 있으며 해당 프로그램의 어느 부분이 실행 중이었는지를 저장하고 있다.

  • 어떤 프로그램이 실행중에 인터럽트가 발생하면 그 프로그램의 실행 상태를 PCB에 저장하고 CPU의 제어권이 인터럽트 처리루틴으로 넘어가게 되며 인터럽트 처리가 끝나면 저장된 상태를 PCB로부터 읽어와 CPU로 다시 원상복귀 시켜 이어서 업무를 처리할 수 있도록 한다.

입출력 구조


컴퓨터 시스템이 컴퓨터 외부의 입출력 장치들과 데이터를 주고받는 것을 말한다.

  • 입출력 방식: 동기식 입출력(synchronous I/O), 비동기식 입출력

동기식 입출력

어떤 프로그램이 입출력을 요청했을 때 입출력 작업이 완료된 후 그 프로그램이 후속 작업을 수행할 수 있는 방식을 말한다.

  • 프로그램이 디스크에서 어떤 정보를 읽어오라는 요청을 했을 때 디스크 입출력이 완료될때까지 시간이 소요되는데, 이때 동기식 입출력은 입출력이 진행되는 동안 그 프로그램의 다음 명령을 수행하지 않고 기다린다. 입출력이 완료되면 인터럽트를 통해 전달되고 CPU 제어권이 프로그램으로 넘어가 다음 명령을 이어서 수행할 수 있게 된다.

CPU의 명령 수행 속도는 빠르지만 입출력 장치에서 데이터를 읽어오는 것과 같이 입출력 연산은 상대적으로 느리다. 따라서 입출력이 완료될 때까지 CPU가 아무 일도 처리하기 못하므로 자원 낭비를 초래하게 된다.
따라서 프로그램의 입출력이 완료되기 전까지 할당받은 CPU를 회수하고 완료가 될 때 CPU를 할당해준다. 입출력이 완료될 때까지 그 프로그램에 CPU를 할당하더라도 명령을 수행할 수 없어서 운영체제는 프로그램을 몇 가지 상태로 나누고 입출력 중인 프로그램의 경우 봉쇄 상태(blocked state)로 전환시킨다. 봉쇄 상태의 프로그램에게 CPU를 할당하지 않고 CPU할당 시 곧바로 명령을 수행할 수 있는 프로그램에게만 CPU를 할당시켜준다.

앞선 내용처럼 입출력이 수행중일 때 다른 프로그램에게 CPU를 양도하게 되면 다수의 입출력 연산이 동시에 요청되거나 처리될 수 있게 된다. 따라서 동기식 입출력에서는 같은 파일에 접근하는 프로그램이 여러개일 경우 의도치 않은 결과가 나올 수 있다.

  • A는 디스크에 원래 1이던 파일의 내용을 3으로 바꾸는 입출력 연산을 요청했고 입출력 연산 수행 중 A에게서 CPU를 빼앗아 B에게 할당한다. B는 A와 같은 파일의 내용을 1 증가시키는 입출력 연산을 요청했다. 이 경우에 매 시점 2개 이상의 입출력 연산을 수행하게 되면 컨트롤러는 A와 B의 순서를 바꾸어 수행할 가능성이 있다.
    A가 입출력을 요청한 다음 B가 요청했다 하면 컨트롤러는 작업을 바꿔 B의 요청을 먼저 처리할 수 있으므로 해당 파일의 값이 1->3->4로 변하는게 아니라 1->2->3이 되어 다른 결과가 나올 수 있게 된다.

따라서 동기식 입출력에서는 입출력 요청의 동기화(synchronization)를 위해 장치별로 큐를 두어서 요청한 순서대로 처리할 수 있도록 한다.

비동기식 입출력

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

  • 어떤 프로그램이 데이터를 디스크에서 읽어오라는 요청을 했을 때 읽어온 내용으로 다음 연산을 수행하기도 하지만 그 데이터와 관련 없이 수행할 수 있는 일이 있다. 비동기식 입출력에서는 데이터와 관련 없는 일을 수행하고 요청한 입출력이 완료되면 관련 데이터 업무를 처리한다.
  • 디스크에서 쓰는 요청이라면 쓰기 작업이 완료되기 전에도 다음 명령을 수행할 수 있으므로 비동기식 입출력이 사용될 수 있다.

비동기식 입출력도 동기식 입출력과 마찬가지로 입출력 연산이 끝나면 인터럽트로 CPU에게 알린다. 그러고 나면 CPU는 그 시점부터 읽어온 데이터를 필요로 하는 명령을 수행할 수 있게 된다.

post-custom-banner

0개의 댓글