[CS] 운영 체제
프로세스란?
프로세스란 응용 프로그램(혹은 서비스)이 Memory(RAM)에 적재되고, CPU를 할당 받아서 실행되는 것을 의미한다.
이때 Memory 적재, CPU 할당은 운영 체제가 담당한다.
프로세스의 메모리 영역으로는 Code, Data, Heap, Stack이 존재한다.
프로세스 제어 블록(Process Control Block, PCB)
프로세스 제어 블록이란 프로세스 실행과 관련된 전반적인 정보를 저장하는 운영체제의 자료구조이다.
운영체제는 프로세스를 관리하기 위해 프로세스의 생성과 동시에 고유한 PCB 를 생성한다. 프로세스는 CPU 를 할당받아 작업을 처리하다가도 프로세스 전환이 발생하면 진행하던 작업을 저장하고 CPU 를 반환해야 하는데, 이때 작업의 진행 상황을 모두 PCB 에 저장하게 된다. 그리고 다시 CPU 를 할당받게 되면 PCB 에 저장되어있던 내용을 불러와 이전에 종료됐던 시점부터 다시 작업을 수행한다.
Context Switching (문맥 교환)
- 기존에 수행 중이던 프로세스에 대해 PCB에 백업
- 새로운 수행할 프로세스에 대해 PCB에 로드
쓰레드(Thread)란?
쓰레드란 프로세스를 구성하는 실행 흐름 단위이다. 따로 쓰레드를 생성하지 않는다면, 1개의 프로세스 당 1개의 쓰레드(Main)가 생성된다. 한 프로세스에 있는 쓰레드끼리는 프로세스 메모리 영역을 공유해서 사용한다. 하지만 각각의 쓰레드마다 Stack은 분리해서 사용한다.
각각의 쓰레드마다 Stack을 분리하는 이유는 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간이므로 쓰레드마다 독립적으로 존재해야 한다.
흔히 프로세스에 비해 쓰레드는 가볍다(경량 프로세스)고 표현한다. 가볍다는 것은 자원(CPU, Memory)이 적게 든다는 것이다.
즉, 하나의 프로세스를 생성하는 것은 CPU의 부담이나 Memory 할당이 더 필요한 반면, 이미 생성된 프로세스에서 쓰레드를 생성하는 것은 CPU의 부담이 Memory 할당이 상대적으로 적다는 것이다.
멀티 프로세스(Multi Process)란?
멀티 프로세스란 하나의 응용 프로그램(서비스)에서 다수의 Process를 동시에 실행하는 것을 의미한다.
하나의 부모 프로세스가 여러 개의 자식 프로세스를 생성한다.
Process는 독립적인 메모리 공간을 사용하기 때문에 하나의 Process에서 문제가 발생한 경우 다른 Process까지 영향을 줄 가능성이 적다. 동일한 서버 역할을 하는 서버 프로세스를 다수 생성하여, 하나의 프로세스에 문제가 생겨도 다른 프로세스를 사용하면 되기 때문에 서비스 안정성을 확보할 수 있다. Context Switching에 대한 Overhead가 있다. (그만큼 자원을 사용한다.)
Process 사이에서는 IPC(Inter-Process Communication)를 통해 자원(메모리)를 공유한다.
멀티 쓰레드(Multi Thread)란?
멀티 쓰레드란 하나의 Process에서 다수의 Thread를 동시에 실행하는 것을 의미한다. 각각의 Thread 사이 에서는 Context Switching 이 없으니 이에 대한 Overhead 또한 없다. 하나의 Process 메모리 공간을 사용하기 때문에 메모리 영역 자체를 공유한다. (IPC를 통한 메모리 공유보다 비용이 적다.) 그러므로 하나의 Thread에서 발생한 문제가 전체 프로세스에 영향을 줄 가능성이 높다.
크롬의 쓰레드 종류? => 브라우저, 다운받는도구, 유튜브 영상
스케줄러
프로세스를 스케줄링하기 위한 Queue 에는 세 가지 종류가 존재한다.
- Job Queue : 현재 시스템 내에 있는 모든 프로세스의 집합
- Ready Queue : 현재 메모리 내에 있으면서 CPU 를 잡아서 실행되기를 기다리는 프로세스의 집합
- Device Queue : Device I/O 작업을 대기하고 있는 프로세스의 집합
각각의 Queue 에 프로세스들을 넣고 빼주는 스케줄러는 아래와 같이 세 가지 종류가 존재한다.
장기 스케줄러(Long-term scheduler or job scheduler)
메모리는 한정되어 있는데 많은 프로세스들이 한꺼번에 메모리에 올라올 경우, 디스크에 임시로 저장된다. 디스크에 저장되어 있는 프로세스에메모리를 할당하여 Ready Queue 로 보낼지 결정하는 역할을 한다.
- 메모리와 디스크 사이의 스케줄링을 담당.
- 프로세스에 memory(및 각종 리소스)를 할당
- degree of Multiprogramming 제어
(실행중인 프로세스의 수 제어) - 프로세스의 상태
new -> ready(in memory)
메모리에 프로그램이 너무 많이 올라가도, 너무 적게 올라가도 성능이 좋지 않은 것이다. 참고로 time sharing system 에서는 장기 스케줄러가 없다. 그냥 곧바로 메모리에 올라가 ready 상태가 된다.
중기 스케줄러(Medium-term scheduler or Swapper)
- 여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄 (swapping)
- 프로세스에게서 memory를 deallocate
- degree of Multiprogramming 제어
- 현 시스템에서 메모리에 너무 많은 프로그램이 동시에 올라가는 것을 조절하는 스케줄러.
- 프로세스의 상태
ready -> suspended
단기 스케줄러(Short-term scheduler or CPU scheduler)
- CPU와 메모리 사이의 스케줄링을 담당.
- Ready Queue 에 존재하는 프로세스 중 어떤 프로세스를 running 시킬지 결정.
- 프로세스에 CPU 를 할당(scheduler dispatch)
- 프로세스의 상태
ready -> running -> waiting -> ready
CPU Scheduling
CPU는 여러 작업을 동시에 수행할 수 없지만, 처리해야할 작업(Process)은 다수이기 때문에 적절한 스케줄링을 통해서 작업을 수행한다.
아주 단순한 스케줄링 방식으로는 먼저 요청(시작)한 프로세스(작업)를 먼저 처리할 수 있겠지만 이와 같은 구조라면 빨리 처리해야 될 작업의 수행이 딜레이 될 수 있고, 처리에 아주 짧은 시간이 소요 되는 작업도 다른 작업에 밀려 오래 기다려야하는 비효율이 발생할 수 있다. 따라서, CPU 스케줄링에는 다양한 알고리즘을 적용하여 합리적으로 작업을 수행한다.
비선점형 스케줄링
어떤 프로세스가 다른 프로세스로 인해 작업 중인 CPU를 선점할 수 없다. 즉, 먼저 작업 중이던 프로세스가 CPU의 점유를 놓아야만 다른 프로세스가 CPU를 점유할 수 있다.
FCFS(First Come First Served)
- 가장 먼저 요청한 프로세스를 가장 먼저 수행
SJF(Shortest Job First) (*선점형과 비선점형으로 나뉨)
- 실행 시간이 짧은 프로세스를 가장 먼저 수행
- 긴 수행 시간을 가진 프로세스의 대기 시간이 매우 길어지거나 수행되지 않는 현상(기아) 발생
우선 순위(Priority) (*선점형과 비선점형으로 나뉨)
- 프로세스에 대한 우선 순위를 둬서 우선 순위가 높은 프로세스를 먼저 수행
선점형 스케줄링
어떤 프로세스가 다른 프로세스로 인해 작업 중인 CPU를 선점할 수 있다. 즉, 먼저 작업 중이던 프로세스가 CPU의 점유를 놓지 않아도 다른 프로세스가 CPU를 빼앗아 점유할 수 있다.
Round Robin(RR)
- 타임 슬라이스(할당 시간)을 프로세스 마다 부여해서 해당 프로세스가 CPU를 점유하기 시작해서 할당 시간 내에 작업을 완료하지 않으면, 해당 프로세스의 작업은 그 상태에서 멈추고 다시 큐에 들어간다.
- 할당 시간이 너무 짧으면 Context Switching이 자주 발생할 수 있기 때문에 비용이 증가하고, 할당 시간이 너무 길면 FCFS 방식과 큰 차이가 없을 수 있다.
SRTF(Shortest Remaining Time First)
- 새로운 프로세스가 도착할 때마다 새로운 스케줄링이 이루어진다.
- 현재 수행중인 프로세스의 남은 실행 시간 보다 더 짧은 실행 시간을 가지는 새로운 프로세스가 도착하면 CPU를 뺏긴다.
Multi-Level Queue(다단계 큐)
- 우선 순위 별로 여러 개의 큐를 두고, 큐 마다 각자 다른 알고리즘을 적용한 것
- Multi-Level Queue를 개선한 Multi-Level Feedback Queue 라는 것도 있다.
Sync vs Async
동기는 데이터의 요청과 결과가 한 자리에서 동시에 일어나는것을 말합니다. 동시에 일어나는 만큼 설계가 직관적이고 간단합니다. 하지만 결과가 주어질 때까지 대기해야하는 단점이 있습니다.
비동기는 요청에 대한 결과가 동시에 일어나지 않는다는 의미입니다. 요청에 대한 결과가 반환되는 동안 다른 작업을 수행할 수 있습니다. 하지만 동기식보다 설계가 복잡합니다.
프로세스 동기화
임계 영역(Critical Section)
동일한 자원을 동시에 접근하는 작업(공유하는 변수 사용, 동일 파일을 사용, ...)을 실행하는 코드 영역을 의미한다. 한 마디로 동시성 이슈가 발생하는 코드 영역이다.
동시성 이슈(Race Condition)
동일한 프로세스 내에 2개 이상의 Process(혹은 Thread)가 동시에 동일한 자원(공유 자원)을 변경하려 고 할 때, 개발자가 의도하지 않은 방향으로 데이터 변경이 발생할 수 있다.
해결 방법
Mutex (뮤택스) (Mutual Exclusion)
공유 자원에 대해서 Process(혹은 Thread)가 사용하는 시점에 Lock을 걸고 사용이 끝난 후에 Unlock 한다.
Semaphore (세마포어)
공유 자원에 대해서 동시에 접근할 수 있는 Process(혹은 Thread)의 수를 제어한다.
Binary Semaphore는 Mutex 와 유사하다.
Counting Semaphore는 다수(N)의 Process(혹은 Thread)가 동시에 공유 자원에 접근할 수 있다.
교착상태(Dead Lock) 필요조건
상호 배제 (Mutual Exclusion)
하나의 프로세스가 공유 자원을 점유하고 있을 때 다른 프로세스는 기다려야한다. (서로 다른 프로세스가 하나의 공유 자원을 동시에 점유할 수 없음)
점유와 대기(Hold and Wait)
특정 프로세스가 공유 자원을 점유한 상태에서 다른 공유 자원을 사용하 기 위해 대기하고 있는 상황이 있어야 한다.
비선점(No preemption)
선점 가능한 자원은 프로세스가 다른 프로세스가 점유한 자원을 강제로 빼앗 을 수 있음. 즉 공유 자원에 대해 비선점하다 는 것은 다른 프로세스가 점유한 자원을 강제로 빼앗을 수 없음을 의미한다.
환형 대기(Circular wait)
각 프로세스가 서로가 서로 필요한 공유 자원을 점유하고 대기하는 형태가 Cycle(원형)을 이루어야 한다.
스와핑(Swapping)
RAM이 부족해질 경우 RAM에 있던 데이터의 일부를 SSD, HDD 등으로 옮기고, 프로세스 수행에 필 요한 데이터를 RAM에 적재한다.
페이지 부재(Page fault)
RAM에 올려져 있을 것으로 예상한 (RAM에 적재되어 있다가 SSD, HDD 등으로 옮겨진) 데이터가 실 제 RAM에 없을 경우를 Page fault 라 한다. (이 때도 동일하게 스와핑이 발생한다.)
단편화(Fragmentation)
프로세스들이 메모리에 적재되고 제거되는 일이 반복되다보면, 프로세스들이 차지하는 메모리 틈 사이에 사용 하지 못할 만큼의 작은 자유공간들이 늘어나게 되는데 이것이 단편화이다.
외부 단편화
메모리 공간 중 사용하지 못하게 되는 일부분. 물리 메모리(RAM)에서 사이사이 남는 공간들을 모두 합치면 충분한 공간이 되는 부분들이 분산되어 있을때 발생한다.
내부 단편화
프로세스가 사용하는 메모리 공간 에 포함된 남는 부분. 예를들어 메모리 분할 자유 공간이 10,000B 있고 Process A 가 9,998B 사용하게되면 2B 라는 차이 가 존재하고, 이 현상이 내부 단편화이다.
Paging(페이징)
하나의 프로세스가 사용하는 메모리 공간이 연속적이어야 한다는 제약을 없애는 메모리 관리 방법이다. 외부 단편화와 압축 작업을 해소 하기 위해 생긴 방법론으로, 물리 메모리는 Frame 이라는 고정 크기로 분리되어 있고, 논리 메모리(프로세스가 점유하는)는 페이지라 불리는 고정 크기의 블록으로 분리된다.
페이징 기법을 사용함으로써 논리 메모리는 물리 메모리에 저장될 때, 연속되어 저장될 필요가 없고 물리 메모리의 남는 프레임에 적절히 배치됨으로 외부 단편화를 해결할 수 있는 큰 장점이 있다.
하나의 프로세스가 사용하는 공간은 여러개의 페이지로 나뉘어서 관리되고(논리 메모리에서), 개별 페이지는 순서에 상관없이 물리 메모리에 있는 프레임에 mapping 되어 저장된다고 볼 수 있다.
- 단점 : 내부 단편화 문제의 비중이 늘어나게 된다. 예를들어 페이지 크기가 1,024B 이고 프로세스 A 가 3,172B 의 메모리를 요구한다면 3 개의 페이지 프레임(1,024 * 3 = 3,072) 하고도 100B 가 남기때문에 총 4 개의 페이지 프레임이 필요한 것이다. 결론적으로 4 번째 페이지 프레임에는 924B(1,024 - 100)의 여유 공간이 남게 되는 내부 단편화 문제가 발생하는 것이다.
Segmentation(세그멘테이션)
페이징에서처럼 논리 메모리와 물리 메모리를 같은 크기의 블록이 아닌, 서로 다른 크기의 논리적 단위인 세그먼트(Segment)로 분할 사용자가 두 개의 주소로 지정(세그먼트 번호 + 변위) 세그먼트 테이블에는 각 세그먼트의 기준(세그먼트의 시작 물리 주소)과 한계(세그먼트의 길이)를 저장
- 단점 : 서로 다른 크기의 세그먼트들이 메모리에 적재되고 제거되는 일이 반복되다 보면, 자유 공간들이 많은 수의 작은 조각들로 나누어져 못 쓰게 될 수도 있다.(외부 단편화)
가상 메모리
다중 프로그래밍을 실현하기 위해서는 많은 프로세스들을 동시에 메모리에 올려두어야 한다. 가상메모리는 프로세스 전체가 메모리 내에 올라오지 않더라도 실행이 가능하도록 하는 기법이며, 프로그램이 물리 메모리보다 커도 된다는 주요 장점이 있다.
Demand Paging(요구 페이징)
ㄴ