안녕하세요!

FE 개발자 유진주입니다.

CS/운영체제

Chapter2. 들어가기 전에 (인터럽트, I/O 방식)

ypearl 2023. 3. 22. 13:35

OS의 목적?

그 전에, 1장에서 배운 운영체제의 덕목에는...

- 사용자가 컴퓨터를 보다 편리하게 사용할 수 있도록 해주어야 한다.

- 하드웨어가 가지는 능력을 십분 발휘되도록 제어해야 한다.

(컴퓨터 자원들을 효율적으로 사용될 수 있게 해야 한다.)

=> 즉, 사용자의 편리성자원의 효율적 사용이 그 목적.

(+) 운영체제 스스로는 효과적인 점검과 개발이 가능하고, 새로운 기능들이 추가될 수 있도록

만들어져서 사용자에게 보다 나은 서비스를 제공해줄 수 있도록 만들어져야 할 것!

 

● 부팅

: 전원 버튼이 눌러져 커널이 메모리에 올라와 실행되어 장치들을 준비시키고, 각종 레지스터 값을 초기화하고 나서 사용자의 입력을 받을 준비를 마치는 것

- 전원이 꺼져 있는 상태에서 운영체제 전부는 디스크에 저장되어 있다.

- 전원이 켜지면 ROM에 저장되어 있는 부트 프로그램(또는 부츠트랩 로더)라는 작은 프로그램이 무조건 제일 먼저 실행되고, 이것이 커널을 찾아 메모리에 올린 후 실행시켜준다.

- 부트 프로그램은 따로 디스크에 있어 부츠트랩 로더가 먼저 부트 프로그램을 메모리에 올려 실행시키면, 부트 프로그램이 커널을 올려 실행시켜준다.

 

 레지스터

: 메모리보다 빠른 기억 장치 (8비트, 16비트, 32비트) *크기 小

- 데이터 레지스터(연산) / 주소 레지스터(데이터나 명령어의 메모리 주소 저장 or 계산) / 코드 레지스터

- MBR, MAR, IR, PC: CPU의 연산을 제어하기 위해 사용되는 레지스터 (위의 레지스터들과는 다른 용도)

(+) 프로그램 상태 워드(Program State Word, PSW): 현재의 상태 정보를 저장 (모든 CPU가 가지는 레지스터).

여러가지 조건(Condition) 코드, 인터럽트 가능/불가능 표시 비트, 그리고 현재 실행 모드 나타내는 비트 등 포함.

 

명령어 처리(Instruction Cycle)

시작->명령어 반입(Fetch)->(Decode)->실행(Execute)->인터럽트 확인 및 처리

* 여기서 instruction은 assembler 단계의 명령이다.

* 명령어 하나가 들어왔을 때 인터럽트 되는 시점: 실행 이후 (실행->인터럽트 확인 및 처리)

 

★ 인터럽트(Interrupt)?

컴퓨터 시스템에 존재하는 각 자원들의 현 상황을 파악할 수 있는 방법.

- 폴링(Polling): CPU가 일정한 시간 간격을 두고 각 자원들의 상태를 주기적으로 확인하는 방식

자원들은 폴링 신호를 받은 후 자신의 상태나 원하는 바를 CPU에게 알려주는데

(부연하면, 자신의 상태를 적어놓을 수 있는 곳에 저장시키고 CPU는 그것을 폴링 때 그것을 읽어본다.),

문제1. 폴링의 간격을 적절히 정해야 한다는 점

문제2. 각 자원들은 직전 폴링 이후 변화된 자신의 상태를 다음 번 폴링 때까지는 알릴 수 없다는 점

(아무 일이 없더라도 CPU는 폴링에 일정량의 시간을 들여야 한다는 부담 또한 발생)

                                                          ↓

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

-> CPU는 따로 시간을 들이지 않아도 되고, 자원들은 상황이 발생하면 즉시 알려 처리 받을 수 있으니 폴링에 비해 훌륭한 방식이다! (오늘날 거의 대부분의 시스템이 채택)

✨ 하드웨어 인터럽트: 하드웨어 자원 즉, 장치 또는 주변장치들로부터의 인터럽트

✨ 소프트웨어 인터럽트: CPU 스스로 자신에게 인터럽트를 해야 할 때가 있는데, 이것은 실행중인 명령어 때문에

생기는 일이니까 소프트웨어 인터럽트라 함.

ex. 명령어 오류 (0으로 나눔, 다른 사용자 주소 참조 등), 시스템 호출

*참고. 트랩(Trap): CPU 스스로 자신에게 인터럽트를 하는 것 (소프트웨어 인터럽트)

 

인터럽트의 처리?

- when?

현재 진행 중인 명령어 실행을 마친 후

*트립은 실행 중에 처리 됨

(처리 중인 명령어에 의해 발생되므로 오류의 경우는 바로 프로그램의 종료가 이루어진다.)

*입출력과 같은 시스템 콜은 입출력이 완료되어야 실행 중인 명령어가 완료되고 이어서 다음 실행문으로 진행됨

 

- how?

- 장치가 인터럽트 신호를 CPU에 보냄

- CPU는 실행 중인 명령어를 완료 시키고 인터럽트 신호를 확인

- 현재 수행 중인 프로그램의 상태 정보를 시스템 스택에 저장 (상태 정보란, PSW, PC의 내용)

- PC에 인터럽트 처리 루틴의   시작 주소를 넣음 -> 처리 루틴이 실행 됨.

- 처리 루틴은 먼저 CPU에 있는 레지스터들의 값을 저장한 후, 필요한 처리 루틴 실행

- 인터럽트 처리가 끝나면 이전에 저장해 둔 레지스터들의 값을 다시 레지스터로 원위치 시킴

- PSW와 PC의 저장된 값을 원래대로 재저장

- 인터럽트가 걸린 다음 명령어부터 실행 재개 됨

 

* PC(Program Counter): 다음에 실행할 명령어의 주소를 기억하고 있는 것

<인터럽트 처리 과정>

 

(+보충설명) 인터럽트?

프로그램을 실행하는 도중, 예기치 않은 상황이 발생할 경우 현재 실행중인 작업을 즉시 중단하고, 발생된 상황을 우선 처리한 후 실행 중이던 작업으로 복귀하여 계속 처리하는 것.

인터럽트 당한 시점의 레지스터와 PC(Program Counter : 다음 번에 실행할 명령어 주소)를 PCB에 저장해두고 CPU의 제어를 인터럽트 서비스 루틴에 넘긴다.

지금 수행 중인 일보다 더 중요한 일(ex. 입출력, 우선 순위 연산 등)이 발생하면 그 일을 먼저 처리하고 나서 하던 일을 계속해야 한다.

외부/내부 인터럽트는 CPU의 하드웨어 신호에 의해 발생
소프트웨어 인터럽트는 명령어의 수행에 의해 발생

 

*문맥교환(Context Switching)이란?

: 현재까지 하던 일에서 잠시 다른 일을 해야할 때, CPU에서 작업한 현재까지의 모양이나 내용을 그대로 가까운 어딘가에 보관해주고, 해야할 다른 일을 다시 CPU에 올리는 것.

문맥: CPU가 하고 있던 일의 상태. (상태 정보를 포함한 처리기 레지스터들의 값들)

 

중첩된 인터럽트의 처리?

1) 순차 처리 방식: 차례대로 하나씩 (현재 처리가 끝난 뒤에 새로 발생한 인터럽트 처리해준다)

2) 중첩 처리 방식: 중첩이 가능하도록

=> 인터럽트 중요도에 따라서 우선순위가 더 높은 경우에는 중첩을, 그렇지 않은 경우에는 순차적으로 구현.

(중첩처리를 하면, 제어스택의 크기가 점점 올라간다.

반면, 순차처리를 하나 쌓고, 끝나면 다음 쌓고 이런 식이라 점점 올라가지 않는다.)

 

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

속도(접근 시간(Access Time)), 용량, 가격(비트(bit)당 단가)의 차이에 의해 분류

- 속도가 빠를수록 가격이 비싼 반면, 용량이 클수록 가격은 싸지만 속도가 느리다는 장단점

=> 따라서, 용도에 맞게 적절히 저장 장치를 계층적으로 구성하게 됨.

<기억 장치의 계층구조>

레지스터

캐시                                                              ↑  용량은 작지만 속도가 빠르고,

★(7장) 주기억 장치(=메모리)                      최소한 컴퓨터에서 프로그램이 실행되어지려면 이 단계에는 와 있어야 한다.

---------------------------------------------------------------

전자디스크                                                   ↓ 전원이 나가도 정보 저장, 속도는 늦지만 대용량

자기디스크                                                     (주로 보존, 저장의 목적으로 사용)

광디스크

자기테이프

 

*참고. 프로그램이 CPU에 의해 실행되기 위해서는 반드시 주기억장치(=메모리)에 있어야 한다!

 

 

I/O 방식 (3)

각각의 입출력 장치에는 컨트롤러가 있고 여기에는 CPU와 입출력할 데이터를 저장하는 버퍼가 있다.

 

CPU의 개입정도(운영방식)에 따라

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

- CPU는 입력을 지시한 후, 한 워드(버퍼의 크기가 한 워드라고 가정)가

  컨트롤러의 버퍼에 입력됐는지를 계속해서 확인하도록 하는 방식

- 인터럽트라는 수단이 필요 없는 대신 CPU가 지속적으로 완료 여부를 확인해야 한다.

=> CPU 사용의 낭비

■ 인터럽트에 의한 입출력(Interrupt-driven I/O)

- 입력을 지시한 후, 한 워드의 입력이 이루어지는 사이에 CPU는 다른 작업에 활용되어지며(장점),

  입력의 완료 시에 인터럽트를 통해 CPU에 알리는 방식

(단점) 완료 되어져도 바로 이루어지지는 않음. (인터럽트를 통해 확인 후에)

하지만, 단점은 장점에 비해 아주 작기에 거의 대부분이 이를 사용한다!

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

(알고보면 인터럽트에 의한 입출력인데, 인터럽트 횟수를 줄이려는 의도를 가짐)

- CPU는 입출력할 데이터의 시작주소와 크기 등을 채널에게 알려주고 다른 작업에 동원되어지며,

  이때부터 입출력은 채널의 주도하에 이루어짐

* 채널: 입출력 작업을 전담하는 프로세서

- 시스템에서 한 번의 입출력 단위를 블록(Block)이라고 부르는데 채널은 블록 단위로

  CPU에게 인터럽트를 보내 처리

- 채널이 직접 메모리를 엑세스한다 : memory cycle stealing 필요

ex. I/O 대량 처리의 경우에서 이용

 

입출력을 위한 하드웨어의 구성에 따라

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

- 입출력 장치들이 입출력 버스(I/O Bus)를 통해 CPU와 연결되어 있는 경우 (가격↑)

- 입출력은 입출력을 담당하는 명령어를 통해 실행 (instruction set↑)

- 입출력 버스를 통해 해당 장치의 지정, 데이터의 전송, 입출력을 구분해주는 제어(Control)값이 전달

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

- 입출력 장치들이 메모리와 함께 메모리 버스에 연결되어 있으며,

  입출력을 위한 명령어를 따로 두어 사용하지 않고 (instruction set -)

  메모리에 대한 명령어(MOVE, LOAD 등)를 사용하여 실제 입출력을 하게 되는 방식

(but, I/O Device로 mapping 되어있는 메모리 영역만큼은 실제 메모리로 사용되지 못한다는 단점)

 

=> 결론(종합). 방식은 Interrupt I/O를 쓰면서, 구성은 lsolated I/O로 하겠다!

 

 

 

'CS > 운영체제' 카테고리의 다른 글

Chapter 6. 교착 상태(Deadlock)  (0) 2023.05.22
Chapter 5. 병행 프로세스와 동기화(1)  (0) 2023.04.14
Chapter 4. CPU 스케줄링  (1) 2023.04.12
Chapter3. 프로세스와 스레드  (0) 2023.04.07
Chapter1. OS란?  (0) 2023.03.16