내용 출처
KOCW 반효경 교수님 <운영체제> 강의
책 <운영체제와 정보기술의 원리>
반효경 교수님의 <운영체제> 강의 내용을 기반으로 정리했으며,
교수님의 저서 <운영체제와 정보기술의 원리>에서 추가할 만한 내용을 이와 같은 인용문 형식으로 추가함.
(사진 출처 : <운영체제와 정보기술의 원리> 98쪽)
CPU는 매 클럭마다 메모리에서 하나씩의 명령(instruction)을 읽어서 실행한다.
Program Counter는 CPU 내부의 레지스터 중 메모리 주소를 가리키는 레지스터다. CPU는 프로그램 카운터가 가리키는 메모리 주소에서 명령을 읽어 온다. 그러면 프로그램 카운터는 다음 주소를 가리키게 된다.
CPU는 하나의 명령을 실행하고, 다음 명령을 실행하기 전에 인터럽트 라인(interrupt line)에서 인터럽트가 들어왔는지를 체크한다. 만약 인터럽트가 들어왔다면, CPU 제어권이 프로그램에서 운영체제로 넘어가게 된다.
인터럽트 벡터 : 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야 할 코드가 위치한 부분을 가리키고 있는 자료구조
운영체제 내부의 인터럽트 벡터는 해당 인터럽트의 처리 루틴 주소를 가지고 있다. 그리고 해당 주소에는 해당 인터럽트를 어떻게 처리할 것인지가 커널 함수로 정의되어 있다. 이를 인터럽트 처리 루틴(=인터럽트 핸들러)라고 한다.
지금 CPU에서 실행되는 것이 운영체제인지 사용자 프로그램인지 구분한다. mode bit가 0이면 운영체제가 CPU 제어권을 가지고, 1이면 사용자 프로그램이 CPU 제어권을 가진다.
interrupt나 exception 발생시 하드웨어가 mode bit를 0으로 바꾼다. 이때 CPU는 모든 기계어 집합을 수행할 수 있다.
운영체제는 사용자 프로그램에게 CPU를 넘기기 전에 mode bit를 1로 세팅한다. 이때 CPU는 제한된 명령만 실행 가능하다. I/O 장치에는 접근할 수 없다.
사용자 프로그램이 CPU를 사용 중일 때는 mode bit가 1이므로, 직접 I/O 장치에 접근할 수 없다. 따라서 사용자 프로그램이 I/O 장치를 사용하고자 할 때는 시스템 콜(System Call)을 한다. 시스템 콜은 사용자 프로그램이 운영체제가 I/O 요청을 하도록 운영체제의 커널 함수를 호출하는 것이다.
사용자 모드인 상태에서 시스템 콜을 하면 커널 모드로 진입한다. 시스템 콜이 끝나면 다시 사용자 모드로 돌아간다. 프로그램의 실행을 끝낼 때는 커널 모드로 진입하여 프로그램을 종료한다.
특권명령은 커널모드에서 운영체제에 의해서만 수행될 수 있는 명령, 시스템의 보안과 관련된 명령이다. 사용자 프로그램이 디스크에 저장된 파일에 자유롭게 접근할 수 있다면 보안상 문제가 발생할 수 있다. 그래서 모든 입출력 명령은 특권명령으로 규정하여, 사용자 프로그램이 직접 입출력을 하는 것을 방지한다.
인터럽트 당한 시점의 레지스터와 프로그램 카운터를 save한 후 CPU의 제어를 인터럽트 처리 루틴에 넘긴다.
[인터럽트의 종류]
Exception이나 System Call은 모두 CPU 제어권이 운영체제에 이양되어 처리된다. 이 과정에서 프로그램 코드가 직접 인터럽트를 발생시킨 후 제어권이 넘어가게 되므로 이들도 넓은 의미에서는 인터럽트의 범주에 포함시키는 것이다.
현재 처리 중인 인터럽트보다 더 높은 우선순위의 인터럽트가 발생하면, 현재 처리 중이던 인터럽트 코드의 수행 지점을 저장하고 우선순위가 높은 인터럽트를 처리한다.
기준 레지스터 (base register) : 어떤 프로그램이 합법적으로 접근할 수 있는 메모리상의 가장 작은 주소 보관
한계 레지스터 (limit register) : 프로그램이 기준 레지스터값부터 접근할 수 있는 메모리의 범위 보관
메모리 접근 연산이 있을 때마다 현재 접근하려는 위치가 합법적인 범위(기준 레지스터 + 한계 레지스터값 사이의 주소 영역)에 있는지 체크한다.
단, 위의 메모리 보호 기법은 하나의 프로그램이 메모리의 한 영역에 연속적으로 위치하는 관리 기법을 사용하는 경우에 한정된 설명이다.
프로그램에 CPU를 넘겨줄 때, 타이머에 일정한 값을 세팅한 뒤 넘겨준다. 타이머의 값을 세팅하는 명령을 로드 타이머(load timer)라고 하며, 이는 특권명령에 속한다.
타이머의 값은 매 클럭 틱(clock tick) 때마다 1씩 감소한다. 값이 0이 되는 순간 타이머가 CPU에 타이머 인터럽트를 건다. 그러면 CPU 제어권이 자동으로 사용자 프로그램에서 운영체제로 넘어가게 된다.
이를 통해 특정 프로그램이 CPU를 독점하는 것을 방지한다.
I/O 장치를 전담하는 일종의 작은 CPU
장치로부터 들어오고 나가는 데이터를 임시로 저장하기 위한 작은 메모리인 local buffer를 가지고 있다.
I/O 장치를 통해서 데이터를 읽거나 쓴 뒤, 로컬 버퍼에 데이터를 저장한다. I/O가 끝났을 경우 interrupt를 발생시켜 CPU에게 그 사실을 알린다.
Direct Memory Access -> CPU와 마찬가지로 메모리에 직접 접근할 수 있다.
DMA 컨트롤러는 로컬 버퍼의 내용들을 모아 직접 메모리에 복사해준다. (원래 CPU가 하는 작업을 대신 한다.) 작업이 끝난 후에는 인터럽트를 한 번 걸어서 CPU에게 작업 사실을 알린다. 이를 통해 CPU가 너무 자주 인터럽트를 당하는 것을 방지해준다.
byte 단위가 아니라 block 단위로 인터럽트를 발생시킨다.
cf) Memory Controller는 CPU와 DMA Controller가 동시에 메모리에 접근하면 충돌이 발생하므로 이를 중재해주는 역할을 한다.
동기식 입출력 (synchronous I/O)
I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에 넘어간다.
입출력 중인 프로그램을 봉쇄 상태(blocked state)로 전환시킨다. 봉쇄 상태의 프로그램에는 CPU를 할당하지 않는다.
동기식 입출력의 경우 I/O가 끝날 때까지 CPU가 낭비된다. 그래서 동기식 입출력을 할 때는 보통 I/O가 완료될 때까지 다른 프로그램에게 CPU를 넘겨준다. 이를 통해 CPU와 I/O 장치를 효율적으로 사용할 수 있다.
큐를 통한 동기성 보장
프로그램 A와 B가 같은 파일에 입출력을 요청했다고 하자. A -> B의 순서로 입출력 요청이 있었는데, 처리가 그 순서대로 되지 않는다면 의도하지 않은 결과가 발생할 수 있다. 따라서 동기식 입출력에서는 입출력 요청의 동기화를 위해 장치별로 큐(queue)를 두어 요청한 순서대로 처리할 수 있도록 한다.
[복습] 큐(queue) = 선입선출(FIFO)의 자료구조
비동기식 입출력 (asynchronous I/O)
I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에 즉시 넘어간다.
두 경우 모두 I/O의 완료는 인터럽트를 통해서 알려준다.
(사진 출처 : <운영체제와 정보기술의 원리> 84쪽)
위로 갈수록 속도가 빠른 대신, 단위 공간당 가격이 비싸서 용량이 적다.
Primary Storage (주기억장치)
Secondary Storage (보조기억장치)
보조기억장치의 용도
① 파일 시스템용
전원이 나가도 유지해야 할 정보를 파일 형태로 보조기억장치에 저장한다.
② 스왑 영역(swap area)용
주로 하드디스크가 사용된다.
메모리의 연장 공간으로서의 역할로, 비휘발성 용도로 사용되는 파일 시스템과는 구분된다.
캐싱(Caching)
용량이 적지만 빠른 저장장치를 이용해 느린 저장장치의 성능을 향상시키는 기법
주로 정보를 재사용하기 위해 쓰인다.
(사진 출처 : <운영체제와 정보기술의 원리> 102쪽)
프로그램은 실행 파일의 형태로 파일 시스템에 저장되어 있다.
프로그램을 실행시키면 이것이 메모리에 올라가서 프로세스가 된다.
프로세스(process) : 현재 수행 중인 프로그램
프로그램을 실행시키면 해당 프로그램의 고유한 주소 공간이 만들어진다. 실제 물리적 메모리의 주소와는 독립적으로 각 프로그램이 독자적인 주소 공간을 가지는 것이다. 따라서 이를 가상 메모리(virtual memory) 혹은 논리적 메모리(logical memory)라고 한다.
이 주소 공간은 code, data, stack으로 구성된다. 이중 스택 영역은 함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시로 저장한다.
주소 변환 : 가상 메모리의 주소를 물리적 메모리의 주소를 변환하는 것
메모리 낭비를 피하기 위해, 프로그램의 주소 공간에서 필요한 부분만 물리적 메모리(physical memory)에 올려놓고, 필요하지 않는 부분은 스왑 영역(swap area)에서 저장한다.
운영체제의 커널도 하나의 프로그램이기 때문에, 코드/데이터/스택의 주소 공간으로 구성되어 있다.
(사진 출처 : <운영체제와 정보기술의 원리> 103쪽)
data : CPU, 메모리, 디스크 등 하드웨어의 종류마다 자료구조를 만들어서 관리한다. 또한 프로세스들을 관리하기 위해 각 프로세스마다 PCB(Process Control Block)가 만들어져 있다.
어떤 프로그램 실행 중 인터럽트가 발생하면 그 프로그램의 실행 상태를 PCB에 저장한 후 CPU 제어권이 인터럽트 처리루틴으로 넘어간다. 인터럽트 처리가 끝나면 저장된 상태를 PCB로부터 CPU 상에 복원해 인터럽트 직전 위치부터 실행이 이어지게 된다.
stack : 현재 수행 중인 프로세스마다 별도의 커널 스택을 두어 관리한다.
사용자 정의 함수
라이브러리 함수
내가 컴파일을 해서 실행 파일을 만들면, 사용자 정의 함수와 라이브러리 함수는 내 프로그램의 코드 영역에 기계어 명령 형태로 존재한다. 함수를 호출할 때는 자신의 주소 공간에 있는 스택을 사용한다.
커널 함수
커널 함수의 종류
- 시스템 콜 함수
ex. read() 함수, write() 함수
- 인터럽트 처리 함수
커널 함수는 커널 코드 내에 들어있는 함수다. 내 프로그램 안에는 커널 함수가 포함되어 있지 않다. 그래서 내 프로그램이 커널 함수를 호출하기 위해서는, 시스템 콜을 통해 CPU 제어권을 커널을 포함하는 운영체제로 넘겨야 한다.
Memory Mapped I/O
I/0 장치에도 메모리 주소를 할당한다. 메모리 접근을 통해 I/O 장치에 접근할 수 있다.