김주균 저자의 OS? Oh Yes - 누워서 보는 운영체제 이야기를 토대로 개인적으로 정리를 한 것 입니다. 어느 상업적인 목적으로 작성하지 않았음을 알립니다.

OS란

첫번째 포스트에서도 나오지만 OS의 사용목적은 사용자의 편리성과 자원의 효율적인 사용을 위해서이다.

부팅

  • 아직 전원을 누르지 않은 시스템은 아직 OS가 디스크에 저장되어있는 상태이다.
  • 전원을 누르게 되면, 그 순간 ROM에 위치한 부트로더 라는 작은 프로그램이 디스크에 있는 부트 프로그램 을 메모리에 올려 실행을 시키면 부트프로그램이 운영체제의 일부인 커널 을 올려 실행 시켜주는 방식을 취한다.

레지스터(Register)

CPU는 여러 개의 레지스터를 가지고 있는데 이것들은 메모리보다 빠른 기억 장치이지만 크기가 작아서 시스템과 사용목적에 따라 8비트, 16비트, 32비트 등의 크기를 가진다.

이름 설명
데이터 레지스터 연산을 위해 사용
주소 레지스터 데이터나 명령어의 메모리 주소를 저장, 계산
인덱스 레지스터 주소 지정을 위해서
세그먼트 포인터 해당 포인터 값을 저장
스택포인터 포인터 해당 포인터 값을 저장
PC 프로그램 카운터
IR 명령어 레지스터
MAR 메모리 주소 레지스터
MBR 메모리 버퍼 레지스터
I/O AR 입출력 주소 레지스터
I/O BR 입출력 버퍼 레지스터

명령어 처리

명령어 하나를 처리하기 위해 어떤 절차가 필요할까?

  1. 우선은 메모리에 있는 명령어를 읽어 처리기에 있는 레지스터로 가져온다.(fetch)
  2. 실행 - 하나의 명령어 처리
  3. 다음 명령어 처리(이때 PC(Program Counter) 레지스터가 다음에 실행해야 할 명령어의 주소를 가지고 있다.)

명령어 실행 순서


인터럽트

인터럽트는 각 자원들이 능동적으로 자신의 상태변화를 CPU에게 알리는 방식이다.

CPU가 일정한 시간 간격을 두고 각 자원들의 상태를 주기적으로 확인하는 방식인 폴링(polling)과는 다른 방식이다.

언제 처리되나?

하드웨어 인터럽트는 현재 진행 중인 명령어 실행을 마친 후 처리

어떻게 처리되나?

처음에 있는 처리기 내의 각 레지스터 값들은 인터럽트 직전의 상황을 나타내므로 PC값이 N+1인 것은 현재 실행 중인 명령어가 N번지에 있던 것이라는 것과, 스택 포인터의 값 T의 메모리 위치를 보면 제어스택(Control Stack)의 맨 아래이고 저장되어 있는 것이 아무것도 없었다는 것을 알 수 있다.

이제 인터럽트의 처리 과정에서 이러한 레지스터 값들을 저장하여야 하므로 그림 처럼 범용 레지스터가 4개였다고 가정한다면 그것들과 PC에 있는 값을 제어 스택에 저장하고 스택 포인터 값을 T-4로 바꾼 다음, PC에는 서비스 루틴의 시작 번지인 Y를 넣어주면 Y번지의 명령어가 실해되는 즉, 서비스 루틴이 실행 되는 것이다. 처리기 내의 범용 레지스터들은 이전 값들을 이미 제어 스택에 저장해 두었으므로 지금부터 치리기 루틴에 의해 얼마든지 사용 가능하다.

서비스 루틴의 마지막 명령어를 실행하게 되면 다음과 같이 사용자 프로그램이 다시 실행될 수 있는 환경을 만들어야 하는데, 스택포인터의 값(T-4)으로 스택에 보관해 두었던 갖ㅅ들을 찾아 범용 및 PC레지스터에 복구하고 스택 포인터 값은 빠진 만큼 다시 T로 조정된다. 이제 PC에 바뀌어 들어간 값이 N+1번지의 명령어를 실행하면 자연스럽게 사용자 프로그램의 실행이 계속될 수 있는 것이다.

명령어 실행 순서


명령어 실행 순서


중첩된 인터럽트의 처리는?

  • 순차 처리 : 언터럽트 처리하는 동안에 발생하는 인터럽트는 현재 처리가 끝난 뒤 바로 처리해주는 방식
  • 중첩 처리 : 중첩이 가능하도록 현재 처리 중인 인터럽트를 잠시 접어두고 또 다른 인터럽트로 실행을 옮길 수 있도록 하는 방식

기억 장치의 계층적 구조(Storage Hierarchy)

  • 속도가 빠를수록 가격이 비싸고, 용량이 클수록 가격은 싸지만 속도가 느리다.

결국 용도에 맞게 적절한 저장 장치를 계층적으로 구성하는 타협이 필요하게 된다.

I/O 방식

입출력을 하기 위해 시스템은 어떤 방식을 사용할까? CPU에 개입에 따라 3가지 정도로 분류를 할 수 있다.
입출력 장치에는 컨트롤러가 있고 여기에는 CPU와 입출력할 데이터를 저장하는 버퍼가 있다.

  1. 프로그램에 의한 입출력(Programmed I/O)

CPU는 입력을 지시한 후 한 워드가 컨트롤러의 버퍼에 입력됐는지를 계속해서 확인하도록 하는 방식, 인터럽트라는 수단이 필요 없는 대신에 CPU가 지속적으로 완료의 여부를 확인하여야한다.

  1. 인터럽트 의한 입출력(Inturrupt-driven I/O)

입력을 지시한 후 한 워드의 입력이 이루어지는 사이에 CPU는 다른 작업에 활용, 입력의 환료 시 인터럽트를 통해 CPU에 알려지는 방식 - 여러번의 인터럽트가 발생하지만, CPU에 낭비를 좀더 없앨 수 있다.

  1. 메모리에 직접 접근하는 입출력(Direct Memory Access, DMA)

채널(Chennel) 이라는 위성 프로세서가 필요한다. CPU는 입출력할 데이터의 시작주소와 크기 등을 채널에게 알려주고 다른 작업에 동원되어지며, 입출력은 채널의 주도하에 이루어지게 된다.

일반적으로 시스템에서 한 번의 입출력 단위를 블록이라고 부르는데 채널은 블록단위로 CPU에게 인터럽트를 보내 알린다.

위의 3개와는 다른 각도에서 입출력을 위한 하드웨어의 구성에 따라 다시 두 가지로 분류할 수 있다.

  1. 독립적인 입출력(Isolated I/O)

입출력 장치들이 입출력 버스(I/O Bus)를 통해 CPU와 연결되어 있는 경우 - 메모리는 따로 메모리 버스를 통해 연결

입출력 버스를 통해 해당 장치의 지정, 데이터, 입출력을 구분해 주는 제어 값이 전달된다.

단점 으로는 명령어가 명령어 집합에 추가되므로 제어 로직이 복잡해지고, 입출력 버스를 장착하는데 추가 비용이 있다.

  1. 메모리 주소지정 입출력(Memory-mapped I/O)

입출력 장치들이 메모리와 함께 메모리 버스에 연결되어 있는 경우. MOVE, LOAD 등을 사용하여 실제 입출력을 하게 되는 방식. 주소 공간만큼의 메모리를 활용할 수 없다는 단점