운영체제(3)-인터럽트의 원리
업데이트:
책
<운영체제와 정보기술의 원리>, 반효경
을 읽고 정리한 내용입니다
프로그램 구조와 인터럽트
프로그램은 함수들로 구성된다. 함수 실행 중에 다른 함수를 호출하고, 호출된 함수의 수행이 끝나면 원래 함수로 돌아가 계속 수행하게 된다.
프로그램이 CPU에서 명령을 수행하려면 수행하려는 주소 영역이 메모리에 올라가 있어야 한다.
프로그램의 주소 영역은 크게 세 가지로 나뉜다.
- 코드
- 프로그램 함수들의 코드가 기계어 명령으로 변환되어 저장되는 영역
- 데이터
- 전역 변수 등 프로그램이 사용하는 데이터를 저장하는 영역
- 스택
- 함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시로 저장하는 데에 사용되는 영역
인터럽트의 동작 원리도 함수와 유사하다.
- A프로그램이 CPU를 할당받아 수행 중 인터럽트 발생
- A는 현재 수행중인 명령의 위치를 저장
- OS 내부 인터럽트 처리 루틴으로 들어가 처리
- A의 작업 지점부터 다시 수행
일반적으로 프로그램 내에서 함수 호출에 필요한 복귀 주소는 각 프로그램에 스택 영역에 보관한다.
반면, 인터럽트 때문에 CPU를 선점당해 저장하는 복귀 주소는 OS kernel 영역에 존재한다.
이 주소를 저장하는 자료구조를 PCB(Process Control Block)이라 한다.
컴퓨터 시스템의 작동 개요
CPU가 수행해야 할 메모리 주소를 담고 있는 레지스터를 Program Counter(PC)라 한다.
컴퓨터 시스템 하드웨어
- CPU
- 일반 명령 : 모든 프로그램이 수행할 수 있다. mode bit = 1
- 특권 명령 : 보안이 필요한 명령. mode bit = 0
- Memory
- kernel mode : PC가 OS가 존재하는 메모리를 가르키고 있다.
- user mode : PC가 사용자 프로그램이 존재하는 메모리를 가르키고 있다.
- I/O Device
- I/O Contoller (작은 CPU)
- Local Buffer
사용자 프로그램이 특권 명령의 수행을 필요로 하면, OS에게 특권 명령의 대행을 요청한다. 이를 System Call이라고 한다.
디스크에서 자료를 읽어오는 System Call
- OS는 user program이 아닌 kernel에 정의된 System Call 코드를 수행
- CPU가 컨트롤 레지스터를 세팅해 디스크 컨트롤러에게 데이터를 읽어오라는 명령을 내림
- 디스크 컨트롤러는 디스크로부터 데이터를 읽어와 자신의 로컬 버퍼에 저장
- 디스크 컨트롤러가 CPU에게 하드웨어 인터럽트를 발생시킴
주변 장치는 CPU의 도움이 필요할 경우 인터럽트로 CPU에게 서비스를 요청한다.
- 주변 장치는 Interrupt line을 설정한다.
- CPU는 매번 명령을 시행한 직후 interrupt line을 체크한다
- 인터럽트가 발생하면 CPU는 해당 인터럽트 루틴으로 넘어가서 처리한다.
프로그램의 실행
“프로그램이 실행되고 있다”란
- 디스크에 있던 실행 파일이 메모리에 적재된다
- 프로그램이 CPU를 할당받고 기계 명령을 수행하고 있다
일반적인 컴퓨터는 CPU가 하나밖에 없으나, 여러 프로그램이 짧은 시간 단위로 CPU를 나누어 쓰므로 메모리에 동시에 적재되어 있을 수 있다.
실행 파일이 메모리에 적재될 때 실행 파일 일부분만 메모리에 올라가고 나머지는 디스크의 특정 영역에 내려가 있는 것이 일반적이다. 프로그램의 주소 공간 중 당장 CPU 수행에 필요한 부분은 메모리에 올리고, 그렇지 않은 부분은 디스크 중 Swap 영역에 내려놓는다.
프로세스의 주소 공간은 code, data, stack 등으로 구성된다. 각 프로그램마다 이러한 주소 공간을 별도로 가지며, 이러한 주소 공간을 Virtual Memory 또는 Logical Memory라고 한다. 이는 실제 물리적 메모리의 주소와 독립적으로 각 프로그램마다 독자적인 주소 공간을 가지기 때문이다.
OS 또한 프로그램이므로 Code. Data, Stack의 주소 공간을 가지고 있다.
- 커널의 Code 영역에는
- CPU, Memory 등 자원 관리를 위한 부분과
- 사용자에게 편리한 인터페이스를 제공하기 위한 부분
- System Call, 인터럽트 처리하는 부분
- 커널의 Data 영역에는 각종 자원을 관리하기 위한 자료구조가 저장된다.
- CPU, Memory 와 같은 하드웨어 자원 관리
- 현재 수행중인 프로그램(프로세스)을 관리. PCB
- 각 프로세스의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지
- 커널의 Stack 영역은 함수 호출 시의 복귀 주소를 저장하기 위한 용도로 사용된다.
- 유저 프로그램의 스택과 달리 현재 수행중인 프로세스마다 별도의 스택을 두어 관리한다.
- 프로세스가 System Call 후 System Call 내부에서 다른 함수를 호출하는 경우
- 그 복귀 주소는 커널 내의 주소가 되어 유저 프로그램의 스택과는 별도의 저장 공간이 필요하게 됨.
- 커널은 일종의 공유 코드이므로 일관성 유지를 위해 각 프로세스마다 커널 내 별도의 스택이 필요함
User Program이 사용하는 함수
프로그램이 사용하는 함수
- 사용자 정의 함수
- 라이브러리 함수
두 함수는 컴파일하여 실행 파일을 만들면 그 프로그램의 코드 영역에 기계어 명령 형태로 삽입된다.
따라서 위 두 함수는 프로그램 실행 시에 해당 프로세스의 주소 공간에 포함된다. 함수 호출 시에도 자신의 주소 공간에 있는 스택을 사용하게 된다.
- 커널 함수
- System Call 함수
- OS의 서비스를 요청
- 인터럽트 처리 함수
- CPU의 서비스를 요청
- System Call 함수
OS kernel의 주소 공간에 코드가 정의된다. 즉, OS 내의 함수를 user program이 호출해서 사용한다.
Interrupt
인터럽트 개념에 대해 다시 정리해 보자
- CPU는 PC가 가리키는 곳에 있는 명령을 수행한다
- CPU가 다른 일을 수행하도록 하기 위해 인터럽트 라인을 세팅해 인터럽트 발생
- PC는 다음 명령을 수행하기 직전에 인터럽트 라인을 체크
- 수행중이던 프로세스를 멈추고 OS의 인터럽트 처리 루틴으로 이동하여 처리
특정 프로세스가 CPU를 독점하는 것을 막기 위해 OS는 Timer 인터럽트 사용
- OS는 CPU를 유저 프로세스에게 이양하기 전 타이머를 세팅
- 유저 프로세스가 해당 시간만큼 CPU를 점유한 뒤 발생하는 타이머 인터럽트 때 CPU를 회수하여 다른 프로세스에 이양
인터럽트 종류
- 하드웨어 인터럽트
- 소프트웨어 인터럽트 (Trap)
- Exception
- 프로그램이 허용되지 않은 연산을 수행하려 할 때
- System Call
- 사용자 프로세스가 특권 명령을 수행하려 할 때
- Exception
인터럽트 용어
- Interrupt Vector
- 여러 인터럽트에 대해 해당 인터럽트 발생시 처리해야 할 루틴의 주소를 보관하고 있는 테이블
- Interrupt Handler
- 실제 인터럽트를 처리하기 위한 루틴
System Call
시스템 콜은 커널이라는 다른 프로그램의 주소 공간으로 이동해야 하므로 일반 함수 호출과는 상이한 방법을 사용한다. 이는 프로그램 자신이 인터럽트 라인에 인터럽트를 세팅하는 명령을 통해 이루어진다.
디스크의 파일 입출력 과정
- 유저 프로그램이 CPU를 점유하고 명령을 수행 중 디스크에서 파일을 읽어와야 함
- 시스템 콜로 커널의 함수를 호출하게 됨
- 유저 프로그램은 CPU 제어권을 OS에게 이양. 이는 인터럽트 라인 세팅 명령으로 이루어짐
- OS는 인터럽트 라인을 보고 입출력 요청 인터럽트임을 알게 됨
- 해당 서비스 루틴으로 이동해 입출력 작업을 수행
- CPU는 디스크 컨트롤러에게 파일을 읽어오라는 명령을 한다.
프로세스의 상태
- 실행 (running)
- CPU를 할당받고 기계어 명령을 수행하고 있는 프로세스의 상태
- 준비 (ready)
- CPU만 할당받으면 당장 수행가능한 상태
- 현재 CPU를 할당받지 못한 상태
- 봉쇄 (blocked, wait, sleep)
- CPU를 할당받더라도 명령을 수행할 수 없는 프로세스의 상태
- ex. 입출력이 진행중인 경우
Ready -> Running
- 실행 상태에 있던 프로세스가 봉쇄 상태가 되거나
- 실행 상태에 있던 프로세스의 CPU할당 시간이 만료되어 타이머 인터럽트 발생한 경우
- OS는 Ready Queue를 두고 제일 앞에 있는 프로세스에게 CPU를 할당한다
- CPU 스케줄링 방법에 따라 큐에 넣는 방식이 달라진다.
CPU 외에도 OS는 자원별로 큐를 두고 있다.
- 입출력 작업이 완료되면 디스크 컨트롤러가 CPU에 인터럽트 발생
- 인터럽트 처리 루틴에 의해 입출력 완료된 프로세스는 입출력 큐에서 빠져나와 CPU 큐에 들어가게 된다.
큐는 소프트웨어 자원을 기다리는 경우에도 필요하다.
- 공유 데이터에 대한 접근 권한은 소프트웨어 자원
- 공유 데이터에 접근중인 프로세스가 다 사용하고 반납할 때까지는 다른 프로세스가 CPU를 할당받았다 하더라도 접근하지 않고 기다려야 한다. (데이터 일관성)
프로세스의 상태 관리는 커널의 주소 영역 중 Data 영역에 다양한 큐를 두어 이루어진다.
- 타이머 인터럽트가 발생하면
- 커널은 자신의 데이터 영역에 있는 준비 큐의 정보를 참조
- 다음으로 CPU를 할당할 프로세스를 결정
- 실행되던 프로세스는 준비 큐의 마지막으로 보낸다.
프로세스의 두 가지 실행 상태
프로세스 A가 CPU에서 실행되고 있다고 하자.
- User Mode Running
- A의 주소 공간에 정의된 코드를 실행한다
- Kernel Mode Running
- 커널의 시스템 콜 함수를 실행한다
시스템 콜이 수행되는 동안 커널이 running state에 있다고 하지 않고 프로세스 A가 실행 상태에 있다고 한다.
다만, A의 코드를 실행하는 것과 구분지어 프로세스 A가 커널 모드에서 실행 중이라 한다.
정리하자면,
- 프로그램이 사용자 정의 함수나 라이브러리 함수를 호출할 때는 사용자 모드에서 실행을 지속
- 시스템 콜을 하는 경우 커널 모드로 진입해 커널의 주소 공간에 정의된 함수를 실행
- 시스템 콜이 끝나면 사용자 모드로 돌아와 이후 명령들을 계속 실행
- 프로그램의 실행이 끝날 때는 커널 모드로 진입해 프로그램을 종료한다.
하드웨어 인터럽트가 발생한 경우도 CPU의 제어권이 user mode에서 kernel mode로 변경된다.
- CPU가 A의 명령을 수행 중 이전에 B가 요청한 입출력이 완료되면
- 입출력 컨트롤러가 하드웨어 인터럽트를 발생
이러한 경우 커널 모드 진입은 B를 위한 것이지만, 인터럽트가 처리되는 동안을 A의 문맥에서 실행된 것으로 간주한다.
즉, A가 실행되던 중 인터럽트 발생하면, 발생 원인과 관계없이 A가 user mode에서 kernel mode로 진입한 것으로 간주한다.
이번 포스팅에서는 인터럽트를 중심으로 여러 컴퓨터 구조 개념들을 정리해보았다.
다음 포스팅은 프로세스 관리에 대해 집중적으로 정리해보자
댓글남기기