OS 운영체제 - 2. CPU
총 네가지를 설명할 겁니다.
1. CPU 구성요소 (사실 이 부분은 컴퓨터 구조와 관련된다. 패스해도 무방) |
1. CPU 구성요소
물론 기계 부품의 내부속까지 알 필요는 없지만, 적어도 CPU의 구성요소들을 알면 아 CPU가 이런 방식으로 돌아가는구나를 이해할 수 있다.
(1) 하드웨어 구조
우선 컴퓨터 하드웨어는 CPU, 메인메모리, I/O bus등으로 이루어지는데
1) CPU는 연산을 담당하고,
2) 메인메모리가 컴파일된 프로그램 코드를 보관하며,
3) I/O Bus는 하드웨어 내부에서 서로 데이터를 주고받기 위해 사용되는 경로다.
(2) CPU코어란
위의 그림은 CPU코어 하나와 외부장치들 간의 관계를 보여주고 있다.
CPU코어는 ALU, CU, Register Set, Bus Interface 등의 요소들로 이루어져 있다.
코어란 CPU에 내장된 처리회로의 핵심부분이다. 과거, CPU엔 당연히 코어가 하나만 존재하였으나 현대에 이르러 기술이 발전하여 CPU에는 두개 이상의 코어가 존재할 수 있게 되었다. 듀얼코어(CPU1개코어2개), 쿼드코어(CPU1개코어4개)
(3) CPU코어 내부구조 - 그림 상단 좌측 회색박스
1) ALU ( Algorithm Logic Unit )
: 실제 연산을 담당. 피연산자를 레지스터에 저장하여 계산하며, 연산결과도 레지스터 중 하나에 저장한다
2) CU ( Control Unit )
: 기억장치에서 실행프로그램을 적절한 순서로 꺼내고 명령어들을 처리하여 ALU에 적절한 신호를 준다
3) Register Set
: CPU 내부 기억장치. 임시 저장소이나 엑세스 속도가 엄청 빠름. 연산관련 데이터, cpu상태, 메모리번지수 등이 저장됨
4) Bus Interface
데이터통로. 버스 인터페이스는 외부 입출력버스와 연결되어 데이터의 Input과 output을 담당합니다. 명령어의 이동통로이기도 합니다.
오키. cpu는 대충 이렇게 이루어져있다.
이제 이런 프로그램을 돌아가게 하기 위해 다음의 CPU자원들을 어떻게 활용하는지 확인해보자.
2. CPU 가상화
코드 해석과 연산의 핵심인 CPU에서는 각 작업들을 어떻게 처리할까
cpu가 하나의 작업을 끝날때까지 잡고 있으면 그동안 다른 작업들은 대기 상태에 놓이게 된다. 큰 작업이 들어온다면 몇분동안 어떤 작업도 할 수 없게 된다는 뜻이다.
이를 방지하기 위해 CPU를 가상화하여 작업을 분산시킬 수 있다.
'가상화'란 CPU에만 사용하는 방법은 아니고 CPU, RAM, Disk, Network등 물리적인 자원에 논리적인 구획을 그어 효율적으로 자원을 관리할 수 있도록 하는 방법을 일컫는다. 즉 논리적인 구획을 그어서 하나의 물리적 자원도 마치 여러개가 존재하는 것처럼 나누어 사용할 수 있게 된다.
(1) 시분할기법 (Time Sharing)
하나의 작업이 오랜 시간동안 묶여 있지 않도록 하나의 작업을 실행하고 일정 시간 후 중단시켜 다른 프로세스를 실행하는 작업을 반복한다. 즉 여러 작업들이 동시에 실행된다고 느껴질만큼 짧은 시간동안 cpu자원을 사용한 후 다른 작업에 양보하여 multi-tasking이 가능하게 한다. 외부의 사용자는 cpu가 여러개의 작업을 동시에 수행하는 것처럼 느끼게 된다.
Context Switch
작업을 중단하고 차후에 다시 수행하기 위해선 그동안 수행했던 작업에 대한 정보를 기록해두어야 한다. 이 정보를 Context라고 한다. A에서 B로 현재 작업을 전환하면서 A작업의 Context는 다음을 위해 저장하고 B작업의 Context로 연산 대상을 전환하는 것을 Context Switch라고 한다.
System Call
운영체제는 커널모드(Kernel Mode)와 사용자모드(User Mode)로 나뉘어 구동된다. 간단하게 중요한 명령어들은 커널모드에서만 사용가능하고 일반적인 명령어들은 사용자모드에서 사용되도록 되어있다. 시스템콜(SystemCall)을 사용하면 이런 커널모드 기능을 운영체제에게 요청할 수 있다.
여기서 중요한 명령어란 보안이 필요한 특권 명령들로 입출력, 타이머와 같은 하드웨어장치에 접근하는 명령어다
Word 프로그램에서 프린터 버튼을 누르면 입출력을 위해서 SystemCall발동 : 사용자모드->커널모드로 전환한다
(2) 프로세스간 전환
시분할기법이 동작하기 위해선 프로세스들이 cpu자원을 어떤 기준으로 넘겨줄 것인가를 정해야 한다.
1) 협조방식 : 시스템콜 기다리기
cpu를 점유하고 있는 프로세스가 trap(시스템콜을 실행하기 위한 명령어)을 보내 System Call이 발동. 다음 프로세스가 cpu자원을 할당받게 할 수 있다.
[프로세스A] | [운영체제] | [프로세스B] |
작업실행(사용자모드) trap명령어: SystemCall(커널모드) |
trap handler가 trap을 처리 저장 후 다음 프로세스로 전환 return-from-trap을 실행 사용자모드로 복귀 |
작업실행(사용자모드) |
2) 비협조방식 : 운영체제가 강제
Timer Interrupt를 발생시켜 운영체제의 Interrupt handler가 현재 프로세스를 중단하고 CPU제어권을 회수한다.
( timer interrupt, interrupt handler .. 이름만 봐도 이들의 역할이 한번에 이해돼죠?)
[프로세스A] | [하드웨어] | [운영체제] | [프로세스B] |
작업실행(사용자모드) | Time Interrupt발생 Context Switch |
interrupt handler가 처리 다음 프로세스로 전환 return-from-trap을 실행 사용자모드로 복귀 |
작업실행(사용자모드) |
3. CPU와 프로세스와 스레드
계속 CPU 작업이라는 말을 썼는데 여기서 작업이 바로 프로세스다.
프로그램은 그저 코드의 형태로 존재한다.
프로그램이 메모리에 올라가면 프로세스가 생성된다.
프로세스가 CPU자원을 할당받아 실행될 때 실행되는 단위가 스레드이다.
프로세스와 스레드에 대해 자세히 살펴보자
프로그램 (코드집합) -> 프로세스 (실행중인 프로그램 또는 프로그램 일부) -> 스레드 (프로세스 내부 실행단위) |
(1) 프로세스
- 프로세스는 '연속적으로 실행중에 있는 프로그램'을 의미한다
- 프로그램은 단순히 실행하려는 명령어의 집합이고 프로세스는 메모리에 올라가 실행되고 있는 프로그램이다.
프로그램 : 정적인 코드집합 <-> 프로세스 : 동적 프로그램
- 따라서 한 프로그램을 실행하기 위해 여러 프로세스가 동시에 존재할 수 있다
- [그림1] 각 프로세스는 생성시 메모리를 할당받는다. 프로세스의 메모리구조는 Code(실제코드), Data(전역변수저장), Heap(동적할당변수저장), Stack(서브루틴정보저장)으로 구성된다(C언어기준)
- [그림2] 프로세스를 관리/제어하기 위해 커널 메모리 안에는 PCB(Process Control Block)이라는 자료구조로 프로세스 정보를 가지고 있다.
- [그림3] 프로세스는 실행되면서 그 상태가 변한다. 프로세스가 creation되어 treminated될 때까지 다양한 상태에 놓일 수 있으며 상태가 하단의 프로세스 상태 전이도를 참고하자. 이때 Interrupt는 코드에러 또는 I/O 호출로 인해 발생한다. 이는 시분할기법을 수행하기 위해 일어나는 trap과는 다르다.
Dispatch : ready -> running | 우선순위가 높은 프로세스가 CPU를 할당받아 실행 |
Timeout : running -> ready | 일정 시간이 지난 프로세스는 스케쥴러에 의해 Context Switch 발생 |
Block : running -> blocked | 입출력 등의 자원요청으로 trap 인터럽트가 발생되어 CPU를 양도하고 대기 (입출력의 경우, 입출력(I/O) 프로세스에게 CPU자원을 양도한다) |
왼쪽부터 프로세스가 사용하는 메모리영역, 프로세스 정보를 담은 자료구조 PCB, 프로세스 상태 전이도.
(2) 스레드
- 프로세스 내에서 실행되는 흐름의 단위, 프로세스가 자원을 할당받아 실행하는 하나의 단위
- 하나의 프로세스를 수행하기 위해 여러 스레드가 동시에 존재할 수 있다. -> 멀티스레딩(Multi-threading)
- 한 프로세스 내에서 순차적으로 실행될 필요가 없는 작업들은 멀티스레딩을 통해 속도를 향상시킬 수 있다
- 스레드는 서로 독립적인 프로세스와 달리 프로세스 내 Code, Data, Heap을 공유한다. 따라서 스레드간 통신이 프로세스간 보다 훨씬 빠르고, 자원소모도 적다. 그래서 웹서버들은 HTTP통신을 멀티프로세스가 아닌 멀티스레드로 구현한다
- 스레드를 이용하면 작업 응답 시간이 단축되지만, 자원공유로 인해 충돌이 발생할 수 있다
프로세스 vs 스레드
Process | Thread | |
자원공유 | 일반적으로 프로세스간 자원공유는 하지 않는다 (하나의 프로그램 내에 존재하는 프로세스들의 경우 예외) | 자원 공유가 원활하다. 경제적. (Stack을 제외한 나머지 공간을 공유) |
통신방식 | IPC를 통해서 가능 | 자유롭게 가능 |
Context Switch | PCB에 정보를 저장하고 전환한다 | Stack영역만 처리하면 되므로 일반적으로 더 빠르고 자원소모가 적다 |
멀티테스킹 | 여러 프로세스를 동시 실행하여 여러 프로그램들을 병렬로 처리 | 여러 스레드를 동시 실행하여 하나의 프로세스를 병렬로 처리 |
cf) IPC = Inter-Process Communication
프로세스간 협력을 위해 취하는 통신방식으로, 두가지의 기본적인 방법이 있다.
1) Message Passing(메세지교환) : 커널(OS)이 대리로 두 프로세스간 메세지 교환. 메모리 보호에 용이. 안전.
2) Shared Memory(공유메모리) : 공유된 메모리를 생성해 두 프로세스가 같이 사용하도록 함. 빠르지만 동기화 문제O.
4. CPU 스케쥴링
지금까지 CPU가 프로세스들을 어떻게 오가며 프로그램들을 수행하는지 이해했다. (-> 시분할기법, System Call)
더 나아가 프로세스 내에는 스레드라고 하는 실행단위가 있어 병렬처리가 가능함도 확인했다. (-> 멀티쓰레딩)
프로세스 실행 순서 결정(4.스케쥴링) -> 프로세스간 전환 방식 설정(2.가상화) -> 멀티쓰레딩 수행(3.스레드)
CPU가 프로세스들을 전환해가며 프로그램들을 수행할때 어떤 순서로 처리해야
사용자 입장에서 빠르게 결과를 받아볼 수 있을까?
'3.CPU와 프로세스와 스레드'-(1)프로세스-[그림3]을 다시 확인하자.
사용자가 요청한 프로그램이 들어오면 그에 따른 프로세스가(또는 프로세스들이) Ready Queue 에 놓이게 된다.
프로세스 상태 전이도[그림3]로는 Ready상태에 있는 것이다.
OS가 실행할 프로세스를 선택하면, 프로세스가 CPU에 올라가서 Running상태가 되는 것이 Dispatch인 것이다!
자, OS는 프로세스들을 어떤 순서대로 실행시킬지를 정해야한다.
어떤 기준으로 스케쥴을 설정하느냐에 따라 장단점이 다르다.
(1) 스케쥴링 기준
Turnaround time(반환시간): 처음 프로세스가 시작한 순간부터 모든 작업이 끝내고 종료할때까지 걸리는 시간
-> 간단히 수행요청을 받고 결과를 받기까지의 시간을 의미한다.
(CPU, waiting, I/O 등 모든 시간을 포함한다.) 반환시간은 짧을 수록 좋다.
Response time(응답시간): 프로세스를 요청하고 처음 실행되기까지 걸리는 시간
-> 작업 중간중간 결과를 받는 시스템(대화형)이라고 할때, 처음 응답을 줄때까지 걸리는 시간을 의미한다.
-> 예를 들면,
'페이지를 클릭해서 다음 페이지가 나올때까지 시간'이 Turnaround time,
'페이지를 클릭하고 처음 반응(로딩 이모티콘)이 보이는 시간'이 Response time 이다.
(2) 스케쥴링 방법
<반환시간을 평가기준으로 둔 스케줄링 방법>
1) FIFO (First In First Out) : 선입선출
시스템에 도착한 순서대로 먼저 온 프로세스부터 실행시킨다
- 오랫동안 자원을 잡아먹는 프로세스가 먼저 들어올 경우 이후의 작은 프로세스들이 큰 프로세스의 종료를 기다리게 됨(convey effect)
2) SJF (Shortest Job First) : 최단작업 우선
자원 사용 시간이 짧은 프로세스부터 실행시킨다.
- 그러나 여전히 자원 사용이 긴 프로세스에 자리를 뺏겨버리면 사용시간이 짧은 프로세스들은 다시 기다려야 한다.
3) STCF (Shortest Time to Completion First) : 최소 잔여시간 우선
언제든 새 작업이 들어오면, 진행중이던 작업의 잔여시간과 새 작업시간을 비교하여 우선순위를 매긴다.
<응답시간을 평가기준으로 둔 스케줄링 방법>
4) RR (Round Robin) : 라운드 로빈
최소 실행시간을 기준으로 정해진 시간만큼 CPU를 할당하고 그 시간이 지나면 다음 프로세스에 다시 기준시간만큼 CPU자원을 할당한다.
- 이때 최소 실행시간을 'Time quantum(타임퀀텀)' 또는 '타임슬라이스'라고 한다.
- 타임퀀텀이 짧으면 응답시간이 짧아지나 문맥교환 비용이 증가하고 반대로 타임퀀텀이 길면 응답시간이 늘어난다.
(1), (2)는 비선점형 스케줄러로, 프로세스가 CPU를 점유하고 있는 동안에는 다른 프로세스가 이를 스탑시킬 수 없다.
(3), (4)는 선점형 스케쥴러로, 프로세스가 종료되기 전에 간섭할 수 있다.