ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [OS101] 운영 체제를 이해하기 위한 컴퓨터 구조 기초
    테크 2023. 9. 5. 19:15

     

    본 글은 2023.09.05에 새롭게 업데이트되었습니다.

     

    서울대학교 평생 교육원에서 제공하는 운영체제의 기초 강의 내용을 중점으로 정리했다. 부족한 부분은 <Operating System Concepts> 책을 참고하면서 채워 나갔다. 이해를 돕기 위한 그림들은 여기에서 가져왔다.

     

    목차

    • 개요
    • 시스템 버스
    • I/O 레지스터
    • 폴링과 인터럽트
    • DMA
    • 하드웨어 보호 기법

     

    개요

    컴퓨터는 크게 연산 작업과 I/O 작업을 한다. 연산 작업은 CPU가 맡아서 처리하는 반면, I/O 작업은 수많은 I/O 디바이스들이 관여한다. 여러 I/O 디바이스들의 기능 및 속도가 매우 다양하기 때문에 운영체제는 이를 효과적으로 제어하기 위해서 I/O 시스템을 가지고 있다. 덕분에 운영 체제의 다른 부분이 I/O 디바이스를 관리하는 일에 신경 쓰지 않아도 된다. 그렇다면 컴퓨터는 어떻게 I/O 작업을 위해 I/O 디바이스와 통신을 할까? I/O 디바이스들은 각각의 I/O 컨트롤러(I/O controller)를 가지고 있다. CPU가 I/O 작업 관련 명령이나 데이터를 버스를 통해 보내면 I/O 컨트롤러 내부에 있는 버퍼 메모리/레지스터로 보내지게 된다. 명령과 데이터를 주고받는 통로를 버스라고 한다. 버스는 통로 역할을 하는 회선뿐만 아니라 내부 통신 규약을 모두 이른다.

     

    CPU와 I/O 사이의 통신을 알아보기 전에 버스에 대해서 구체적으로 알아볼 것이다. 그리고 I/O 디바이스가 외부 장치와 통신을 하기 위한 인터페이스 역할을 하는 I/O 레지스터를 살펴보겠다. I/O 레지스터에 접근하는 방법은 두 가지가 있는데 이에 대해서도 자세히 살펴보겠다. 그리고 CPU가 I/O 장치가 준비되었는지 확인하는 방법인 폴링(polling)과 인터럽트(interrupt)에 대해서 공부한 후, CPU 개입없이도 I/O 장치가 메모리에 접근할 수 있는 DMA에서도 알아보겠다. 마지막으로 하드웨어를 보호하기 위해서 어떠한 보호 기법이 있는지 살펴보겠다.

     

    시스템 버스

    시스템 버스
    시스템 버스

    버스는 크게 컨트롤 버스(control bus), 주소 버스(address bus), 그리고 데이터 버스(data bus)가 있다. 버스가 할 수 있는 트랜잭션은 읽기, 쓰기, 읽기/쓰기이다. 버스 트랜잭션을 하기 위해서 버스 마스터(bus master)가 버스를 장악하는 일을 수행한다. 버스 마스터의 예로는 CPU, I/O 컨트롤러, DMA 컨트롤러 등이 있다. 여러 버스 마스터들이 동시에 버스를 장악하려 할 수 있다. 이 경우 버스 중재자(bus arbiter)가 특정 버스 마스터에게 승인 시그널(grant signal)을 준다. 인터럽트 구동 I/O(interrupt driven I/O)나 DMA I/O 방식은 CPU의 관제 없이 버스 장악이 가능하다. I/O 컨트롤러의 경우 내부에 버퍼 메모리/레지스터가 존재하기 때문에 CPU의 관제 하에 움직이는 버스 슬레이브(bus slave)-데이터를 담고 있는 장치, 데이터를 담고 있기 때문에 주소도 필요함-로 동작할 수도 있다.

     

    I/O 레지스터

    CPU가 메모리와 통신하기 위해 MAR(Memory Address Register), MBR(Memory Buffer Register)와 같은 인터페이스가 존재하는 것처럼 I/O 디바이스도 외부 장치들과 통신하기 위해 여러가지 종류의 인터페이스 역할을 하는 레지스터가 존재한다.

    • 데이터-인 레지스터 (Data-In Register): I/O 디바이스에 의해 입력된 정보를 저장한다. CPU가 입력을 얻기 위해 읽기를 수행한다.
    • 데이터-아웃 레지스터 (Data-Out Register): I/O 디바이스에 의해 출력될 정보를 저장한다. CPU가 자료를 출력하기 위해 쓰기를 수행한다.
    • 상태 레지스터 (State Register): 현재 명령이 완료되었는지, 에러가 있었는지 등을 저장하고 있다.
    • 컨트롤 레지스터 (Control Register): CPU가 주변 장치에게 I/O 명령을 내리거나 통신 방법을 선택하기 위한 정보를 저장하고 있다.

     

    I/O 레지스터에 접근하기 위해서는 두 가지의 방법이 있다.

    • port mapped I/O: I/O 레지스터가 메모리 주소 공간과 별도로 존재하는 방식이다. I/O 레지스터에 접근하는 명령어가 별도로 존재한다. 또한 이를 위해 별도의 I/O 버스가 존재한다. 인텔의 경우 이 방식을 사용한다.
    • memory mapped I/O: I/O 레지스터가 메모리 주소 공간과 분리되어 있지 않고 메모리 공간의 일부분을 I/O 디바이스의 메모리/레지스터로 사용하는 방식이다. 따라서 일반 데이터에 접근하는 명령어와 I/O 관련 데이터에 접근하는 명령어가 동일한다. 이 별도의 공간은 일시적일 수도 있고 영구적일 수도 있다. ARM과 같은 RISC의 경우 이 방식을 사용한다.

     

    폴링과 인터럽트

    I/O 디바이스가 준비되었는지 아닌지 살펴보는 기법으로 아래의 두 가지가 있다.

    • 폴링
    • 인터럽트

     

    폴링

    I/O 동작이 완료될 때까지 CPU가 반복적으로 I/O 컨트롤러의 상태 레지스터가 busy인지 아닌지를 확인하는 방법이다.

     

    인터럽트

    I/O 동작이 완료되면 I/O 컨트롤러가 CPU에게 비동기적으로 완료되었음을 알려주는 방식이다. CPU는 기본적으로 인터럽트 요청 라인(interrupt request line)을 가지고 있다. CPU는 한 명령어가 끝날 때마다 매번 이 라인을 검사한다. I/O 컨트롤러가 이 라인에 신호를 보내면(인터럽트가 발생하면) CPU가 한 명령어 수행을 끝낸 후 각종 레지스터 값과 상태 정보들을 저장한 다음 메모리 상의 인터럽트 서비스 루틴(Interrupt Service Routine, ISR)-인터럽트 핸들러(interrupt handler)와 같은 말-으로 점프한다. 인터럽트 핸들러는 인터럽트의 발생 원인을 조사하고 필요한 작업을 수행한 후 CPU를 인터럽트 전의 실행 상태로 되돌리기 위해 return from interrupt 명령을 실행한다.

     

    인터럽트는 보통 IRQ(Interrupt ReQuest number)라는 작은 정수를 통해서 특정 인터럽트 핸들러가 실행된다. 이 IRQ는 인터럽트 벡터 테이블(interrupt vector table)의 인덱스로 사용된다. 이 테이블은 인터럽트 핸들러들의 시작 주소들을 가지고 있다. 대부분의 CPU들은 두 종류의 인터럽트 요청 라인을 가지고 있다. 하나는 마스크 가능한 인터럽트(nonmaskable interrupt) 용이고, 다른 하나는 마스크 불가능한 인터럽트(maskable interrupt)용이다. 마스크 불가능한 인터럽트는 인터럽트 되어서는 안 되는 주요 명령을 수행하기 위해서 존재한다. Intel Pentium 프로세서에서 처음 0번에서 31번까지의 이벤트들은 마스크가 불가능한 것으로 여러 오류 상황을 알린다. 32번에서 255번까지의 이벤트들은 마스크가 가능한 것으로 하드웨어가 생성한 인터럽트 등에 사용된다.

     

    인터럽트 기법은 인터럽트 우선 순위 레벨(interrupt priority level)의 구현이 가능하다. 대부분의 인터럽트에 비해 낮은 우선순위를 가지는 소프트웨어 인터럽트 또는 트랩(trap)은 시스템 호출(system call)이나 프로그램 수행 중 오류를 처리할 때 발생한다. 일반적으로 프로그램은 시스템 호출(system call)을 수행하기 위해 라이브러리 루틴(library routine)을 호출한다. 그 라이브러리 루틴은 호출 인자를 점검한 후 트랩을 발생시킨다. 트랩이 발생하면 현재 코드 상태를 저장한 후, 커널 모드로 전환되어 특정 커널 루틴을 수행한다. 이에 대한 구체적인 설명은 하드웨어 보호 기법에서 하겠다.

     

    DMA

    DMA는 Direct Memory Access의 줄임말로 CPU의 개입없이 I/O 컨트롤러가 메모리에 직접 접근하여 데이터를 읽거나 쓸 수 있도록 하는 것이다. 폴링이나 인터럽트는 character I/O 오퍼레이션을 수행하지만 DMA의 경우는 block I/O 오퍼레이션을 수행한다.

     

    CPU는 블록 단위의 데이터를 읽기 위해서 DMA 컨트롤러에게 아래의 3가지 정보를 제공한다.

    • 읽기 작업인지 쓰기 작업인지
    • 블록 시작 주소
    • 블록의 크기

     

    DMA 수행이 끝나면 인터럽트를 날린다.

     

    블록 데이터를 옮기는 방식에는 두 가지가 있다.

    • cycle stealing 방식: CPU가 버스를 사용하지 않을 때만 DMA 컨트롤러가 버스를 사용하는 방식이다. CPU 성능에는 영향이 없지만 DMA가 느려지게 된다.
    • block transfer 방식: CPU와 대등하게 CPU, DMA가 각 버스 마스터가 되는 것이다.  CPU 성능에는 영향을 끼칠 수 있으나 DMA 속도는 빠르게 된다.

     

    하드웨어 프로텍션

    기본적으로 사용자 프로그램은 컴퓨터 입장에서 봤을 때 신뢰되지 않는다. 버그나 취약점이 존재할 확률이 매우 높기 때문이다. 만약 이러한 사용자 프로그램이 잘못된 수행을 하여 운영 체제에 영향을 끼친다면 매우 큰 문제를 발생시킬 수 있다. 그래서 컴퓨터는 사용자 모드커널 모드로 나누어져 있다. 하드웨어의 프로세서 상태 단어(processor status word)에는 모드 비트가 존재한다. 모드 비트가 0인 경우, 커널 모드로 수행된다. 반면, 모드 비트가 1인 경우, 사용자 모드로 수행된다. 커널 모드로 바뀌면 특권 명령(privileged instruction) 수행 권한과 모든 메모리에 접근할 수 있는 권한을 받게 된다.

     

    커널 모드로 전환이 일어나기 위해서는 커널에 위치해야 한다. 모드를 바꾸는 매우 중요한 작업이기 때문이다. 그러나 전환이 일어나기 전까지는 사용자 모드에 위치하고 있다. 어떻게 전환이 일어나는 것일까? 정답은 트랩이다. 특권 명령을 수행을 위해 몇 가지 검사를 한 후 트랩이 발생한다. 그 후 인터럽트 핸들러가 뜨면 해당 핸들러가 모드를 바꾼다.

Designed by Tistory.