Multi Programming
과거에는 컴퓨터라는 것이 굉장히 특별한 용도로 사용이 돼서 하나의 프로그램만 실행할 수 있었습니다.
하지만 이 방식은 CPU가 노는 시간이 많았기 때문에 CPU 이용률을 높이기 위해서 Multi-programming이 제안되었습니다.
멀티프로그래밍은 프로그램을 여러 개 띄운다는 뜻입니다. CPU에는 하나의 프로그램만 실행되고 나머지 프로그램들은 대기열에서 관리합니다. 이 때문에 돌고 있던 프로그램이 대기해야 되는 경우 어떤 프로그램도 CPU를 사용하지 못하게 되어 CPU 이용률이 낮아집니다.
따라서, CPU 상의 프로그램이 잠시 멈춰야 될 때가 발생하면
- 해당 프로그램을 CPU에서 내리고 대기열 맨 뒤로 집어 넣습니다.
- 대기열 맨 앞의 프로그램을 꺼내서 CPU에 올리고 실행합니다.
이렇게 CPU 상에 올라가는 프로그램이 변경될 때 "Context Switching이 필요합니다.
CPU안에는 레지스터라고 하는 굉장히 제한된 저장 공간밖에 없습니다.
CPU는 굉장히 고속으로 동작하고 우리가 빠르다고 생각하는 메모리조차도 CPU에 비하면 매우 느립니다.
그러나 모든 데이터를 레지스터에 넣고 전부 CPU속도로 진행할 수 없어 레지스터에는 빠른 변수 수준의 저장할 수 있는 데이터만 갖고 있습니다.
CPU는 다음 실행 할 명령을 레지스터에 Instruction Pointer와 Instruction Counter로 가리키고 있다가 메모리에서 읽어와 처리합니다. 이렇게 CPU가 실행하는 프로그램을 변경할 때 CPU입장에서는 실행 중인 전체 메모리를 내려야 하니 부하가 큽니다. 그래서 콘텍스트 스위칭이 많이 발생하면 CPU 입장에서는 비효율적입니다. 컨텍스트 스위칭을 하는 동안 CPU는 아무것도 하지 않고 있으니 cpu utilization 또한 내려갑니다.
정리하면 멀티프로그래밍은 프로그램을 여러 개 돌리지만 앞에 있는 프로그램이 잠들면 바꾸는 방식입니다. 그러나 이 멀티프로그래밍은 앞에 프로그램이 잠을 자지 않으면 뒤에 있는 프로그램이 한정 없이 기다려야 하는 상황이 발생합니다.
이렇게 뭔가를 받지 못하고 한정 없이 기다리는 것을 "기아(starvation)"라 합니다. 따라서 이 경우는
"나머지 프로그램들은 CPU starvation 상태다"라고 합니다.
Multi Tasking
멀티프로그랭의 기아상태를 방지하기 위해서 Multi Tasking은 시간 단위로 쪼개서 실행하게 하자고 제안합니다.
그것을 작은 단위로 Task라고 합니다. 이 멀티태스킹은 프로그램이 스스로 대기 상태가 되지 않더라도 OS가 강제로 바꿉니다.
Time Sharing
Multi Tasking의 Time Sharing이란 CPU를 점유할 수 있는 시간을 잘게 쪼개서
여러 프로그램이 이 시간 동안만 CPU를 사용하게 하는 것입니다.
이렇게 잘게 쪼개진 시간 단위를 "time quantum" 또는 "time slice"라고 합니다. (대개 수 밀리초 ~ 수백 밀리초)
이렇게 시간을 잘게 쪼개서 실행하다 보면 동시에 실행된다는 것을 느끼게 됩니다.
이를 동시성(Concurrency)라고 합니다.
Multi-tasking OS에서의 Process Life Cycle
- Started: 프로세스가 처음 생성될 때의 초기 상태
- Ready: 프로세스가 실행되기 위해 OS로부터 CPU 할당을 기다리는 상태
- Running: 프로세스가 CPU를 할당받아 기계어 코드를 실행하는 상태
- Running → Ready: CPU time slice를 다 쓴 경우
- Running → Waiting: Blocking 함수를 호출한 경우
- Waiting: I/O등의 리소스를 기다리느라 CPU를 반납하고 기다리는 상태
- Terminated: 종료되어 메모리 등의 자원을 완전히 반환하는 상태
새로운 프로그램이 실행되면 CPU 사용할 준비가 됐다고 알립니다.
그러면 CPU에 올라가게 되고 CPU를 열심히 씁니다.
멀티프로그래밍에서는 기다려야 하는 상황이 되면 CPU로 내려옵니다.
그러나 멀티 태스킹에서는 사용 시간이 지나면 내려가게 됩니다.
프로그램의 할 일이 모두 수행됐으면 최종적으로 Terminated 상태가 되고 메모리 등의 자원을 완전히 반환합니다.
Multi-tasking의 예
현재 CPU Queue에는 P1, P2, P3가 대기하고 있습니다.
그리고 Resouce별로 Queue가 존재합니다. 디스크, 네트워크, 뮤텍스의 락 등등도 각각의 Queue가 존재합니다.
P4는 디스크 큐에서 대기 중인 상태입니다.
그럼 P1을 실행하겠습니다.
P1이 잘 실행되고 있습니다. 그러다가 P1의 시간이 다 되면
P1은 CPU Queue의 맨 끝으로 돌아갑니다. 시간이 다 돼서 강제로 뺏긴 상태입니다.
그럼 다음 순서인 P2가 CPU에 올라가게 됩니다.
P2가 올라갔는데 이 프로세스는 recv() 함수를 호출했습니다.
recv()는 네트워크와 관련이 되어 있으므로 네트워크 큐로 내려갑니다.
CPU 관점에서는 P2를 안 쓰고 있는 것입니다.
그리고 그다음 순서인 P3가 올라가게 됩니다.
P3가 실행되는 도중 P2의 recv()가 데이터를 받았습니다.
그럼 이 P2는 네트워크 큐에서 빠지고 다시 CPU 큐에 들어가게 됩니다.
그래서 P2는 다시 CPU가 실행을 할 수 있는 상태가 됩니다.
이 구조는 불필요한 프로세스가 CPU 큐에서 계속 있지 않게 함으로써 CPU의 효율을 향상합니다.
'CS' 카테고리의 다른 글
[OS] C++의 Thread (1) | 2023.12.12 |
---|---|
[OS] Multi-processing, Multi-threading (0) | 2023.12.10 |
[OS] CPU utilization, CPU load (1) | 2023.12.10 |
[Network] Socket Options, I/O Multiplexing과 Non-blocking I/O (1) | 2023.10.23 |
[Network] TCP Socket Programming - 데이터 수신하기 (1) | 2023.10.22 |