프로세스와 스레드의 차이
- 프로그램 : 파일 단위로 저장 장치에 저장되어 있으며, 아직 실행되지 않은 상태의 코드 덩어리를 의미한다.
프로세스
프로세스는 운영체제로부터 메모리 공간을 할당 받아 실행 중인 프로그램이다.
프로세스에 할당되는 메모리 영역
코드(Code), 데이터(Data), 힙(Heap), 스택(stack) 영역
- 코드 영역 : 프로세스가 실행할 코드가 기계어의 형태로 저장된 공간이다. (컴파일 타임에 결정, Read-Only)
- 데이터 영역 : 전역 변수, static 변수 등이 저장된 공간이다. 전역 변수, static 변수를 참조한 코드는 컴파일하고 나면 데이터 영역의 주소값을 가르킨다. (컴파일 타임에 결정, Read-Write : 실행 도중 변경 가능)
- 힙 영역 : 프로그래머가 관리하는 메모리 영역으로, 힙 영역에 메모리를 할당하는 것을 동적 할당이라고 한다. (런타임에 결정, 스택보다 할당할 수 있는 메모리 공간이 많으나 데이터 읽고 쓰기가 느림)
- 스택 영역 : 함수 안에서 선언된 지역변수, 매개변수, 리턴값, 복귀 주소 등이 저장된다. 스택의 LIFO 방식에 따라 함수 호출 시 기록하고 종료되면 제거한다. (컴파일 타임에 결정, 정해진 크기가 있으므로 stack overflow 에러 발생 가능)
프로세스 제어 블록 (Process Control Block, PCB)
PCB는 특정 프로세스에 대한 정보를 담고 있는 운영체제의 자료구조이다. 프로세스는 운영체제의 스케줄링 알고리즘에 따라 CPU를 할당받는다. 작업을 진행하다가 프로세스 전환이 발생하면 하던 일을 저장하고 CPU를 반환해야 한다. 그리고 나중에 스케줄링에 의해 재실행되었을 때 이전에 어디까지 작업이 진행되었는지 그 정보를 알아야 한다. 그 정보가 담긴 공간이 PCB이다. 프로세스 생성과 동시에 그 프로세스의 고유한 PCB도 함께 생성된다.
스레드
스레드는 프로세스를 구성하는 독립적인 실행 단위이다. 스레드는 같은 프로세스 내 다른 스레드와 메모리 영역을 공유할 수 있다.
- 스레드도 하나의 실행 흐름이므로 실행과 관련된 데이터가 필요하다.
- 독립적 : 각 스레드는 자신만의 고유한 스레드 ID, 프로그램 카운터 (PC), 레지스터 집합, 스택 영역을 가진다.
- 공유 : 그리고 속한 프로세스 내의 코드/데이터/힙 영역과 기타 운영체제 자원 (열린 파일, 신호 등) 을 다른 스레드와 공유한다.
- 각 스레드는 스택 영역을 통해 독립적인 실행 흐름을 가진다.
- 스레드는 프로세스 메모리 영역을 공유하기 때문에 어떤 스레드 하나에서 오류가 발생하면 같은 프로세스 내의 다른 스레드 모두가 강제로 종료된다. (프로세스는 한 프로세스가 강제 종료되어도 공유 자원을 손상시키는 경우가 아니라면 다른 프로세스에게 영향을 주지 않는다.)
멀티 프로세스와 멀티 스레드
멀티프로세스
- 멀티프로세싱? 하나의 응용프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 처리하도록 하는 것
- 장점 : 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽는 것 이상으로 다른 영향이 확산되지 않는다.
- 단점
- Context Switching에서의 오버헤드
- Context Switching 과정에서 캐시 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되어 오버헤드 발생
- 프로세스는 각각 독립된 메모리 영역을 할당받았기 때문에 프로세스 사이에서 공유하는 메모리가 없어, Context Switching가 발생하면 캐시에 있는 모든 데이터를 리셋해야함
- 프로세스 사이의 어렵고 복잡한 통신 기법(IPC)
- 프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없다.
멀티 스레드
- 멀티 스레딩? 하나의 응용프로그램을 여러개의 스레드로 구성하고 각 스레드로 하여금 하나의 작업을 처리하도록 하는것이다.
- 장점
- 시스템 자원 소모 감소
- 프로세스를 생성하는게 스레드 생성하는것보다 자원 많이 듦
- 시스템 처리량 증가
- 스레드 데이터영역 공유하고 있어 자원 공유 간단
- 스레드 사이의 작업량이 작아 Context Switching 빠름
- 간단한 통신 방법으로 인한 프로그램 응답시간 단축
- 스레드는 프로세스 내의 stack영역을 제외한 모든 메모리 공유해 통신 부담 적음
- 단점
- 설계, 디버깅 까다롭다.
멀티 프로세스 vs 멀티 스레드
멀티 스레드를 사용하면?
프로그램을 여러 개 키는 것보다 하나의 프로그램 안에서 여러 작업을 해결할 수 있다.
여러 프로세스로 할 수 있는 작업들을 하나의 프로세스에서 여러 스레드로 나눠가면서 하는 이유는?
1. 자원의 효율성 증대
프로세스는 독립적인 영역을 가지고 스레드는 스택 제외 공유 영역을 가짐
프로세스 생성 시간, 자원>>>스레드 생성 시간, 자원
-> 시스템 자원 소모 준다.
2. 처리 비용 감소 및 응답 시간 단축
같은 문맥으로 프로세스는 공유하는 영역이 없어
프로세스 IPC 통신>>>스레드 간 통신
전환 속도 빠름
주의할 점
- 동기화 문제 -> 공유 자원을 사용하므로 충돌 발생 위험
https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html
프로세스 스케줄링
각 CPU 코어는 한번에 한 프로세스를 실행할 수 있다. 따라서 단일 CPU 코어 시스템에 반해 멀티 코어 시스템은 한 번에 여러 프로세스를 실행할 수 있다.
- 멀티 프로그래밍 (multiprogramming) : CPU 사용률을 최대화하기 위해 항상 프로세스를 실행하도록 한다. 어떤 프로세스가 CPU를 사용하다가 I/O 작업 등 CPU를 필요로 하지 않는 순간이 오면 다른 프로세스가 CPU를 사용할 수 있도록 한다.
- 시분할 (time sharing) : 각 프로그램이 실행되는 동안 사용자들이 상호작용할 수 있도록 프로세스 간 CPU 코어를 자주 전환하는 것이다. CPU가 하나의 프로그램을 수행하는 시간을 매우 짧은 시간(ms)으로 제한하여 프로그램을 번갈아 수행하도록 하면 CPU가 하나인 환경에서도 여러 사용자가 동시에 사용하는 듯한 효과를 가져올 수 있다.
프로세스 상태
- New : 프로세스가 생성됨
- Running : 프로세스의 Instruction이 실행됨
- Waiting : (I/O 작업 완료나 신호 수신과 같은) 이벤트가 발생하기를 기다림
- Ready : 프로세서에 할당되기를 기다림
- Terminated : 프로세스가 실행을 끝냄
스케줄러의 종류
어떤 프로세스에게 자원을 할당할지를 결정하는 운영체제 커널의 모듈을 말한다.
현재는 장기 중기는 거의 사라진채 단기 스케줄러만 남아있다. 단기 스케줄런ㄴ CPU 스케줄러라고 부른다.
1. 장기 스케줄러 (= 작업 스케줄러)
수행해야 할 job이 10개이고 메모리는 6개 밖에 올릴 수 밖에 없을 때, 6개를 선택해야 한다. 이게 장기 스케줄러가 하는 일이다.
: 어떤 프로세스를 준비 큐에 삽입할지 결정
풀로부터 프로세스들을 선별하고 실핼하기 위해 메모리에 적재
프로세스의 상태 : new -> ready (in memory)
2. 단기 스케줄러 (= CPU 스케줄러)
6개가 메모리에 적재되었다 할지라도 cpu를 차지하는 프로세스는 한개이다.
: 준비 상태의 프로세스 중에서 cpu 할당할 프로세스를 결정
단기인 이유? cpu가 놀지 않도록 짧게 교체되니깐
프로세스의 상태 : ready -> running -> waiting -> ready
3. 중기 스케줄러
6개를 메모리에 적재했는데 감당이 안된다 빼야한다.
: 메모리에 적재된 프로세스 수를 동적으로 조절하기 위해 추가된 스케줄러
프로세스의 상태 : ready -> suspended
https://jhnyang.tistory.com/372
https://velog.io/@eu_nzi/운영체제-스케줄러의-종류-단기-중기-장기
CPU 스케줄러
FCFS
SJF
SRT
Priority scheduling
RR
동기와 비동기의 차이
프로세스 동기화
Critical Section(임계구역)?
- 동일한 자원을 동시에 접근하는 작업을 실행하는 코드 영역
-> 멀티 쓰레딩의 문제점이 발생
Ctritical Section Problem
여러 스레드가 들어오면 무결성 보장 못함 -> 공통된 영역에 하나의 프로세스만 들어 갈 수 있도록 설계 하는 것. 이러한 설계를 위해 세가지 요구조건이 충족되어야함
1. Mutual Exclusion 상호베타
어떠한 task가 Critical section을 사용중이면 다른 task는 사용이 불가능
2. progress
현재 Critical section을 사용중인 task가 없고 임계구역에 들어가길 원하는 task가 있다면 바로 들여보내줌
3. Bounded waiting
한정된 대기 시간을 가져야한다. -> 무한대기 막아줌
하드웨어를 통한 해결책
Memory Barriers
Compare & Swap
Atomic Variables.
Software Solution
메모리 관리 전략
메모리 관리 배경
- 성능을 향상하기 위해서는 메모리에 여러 개의 프로세스가 올라와 있어야 한다.
- 제한된 물리 메모리의 효율적인 사용과 메모리 참조 방식을 제공하기 위한 전략 필요
Paging
논리주소의 메모리를 고정된 크기의 페이지로 나눠 관리하는 기법이다.
- 물리주소 공간(Physical address)은 연속적이지 않을 수 있다(noncontiguous)
- 페이지는 모두 같은 크기를 가진다.
- 물리주소 공간을 페이지와 같은 사이즈로 나눈 것들을 프레임이라고 한다.
- 페이지 테이블을 이용해 논리주소에서 프레임을 가리키는 물리주소로 매핑한다.
- 외부 단편화는 발생하지 않으나, 내부 단편화는 발생한다.
페이지 테이블?
논리주소의 페이지를 물리주소의 프레임으로 매핑시켜주는 정보를 답고 있는 테이블이다.
Segmentation
논리적 내용을 기반으로 나눠서 메모리에 배치하는것을 의미한다. 세그멘테이션은 프로세스를 세그먼트의 집합으로 표현한다. code영역, data영역, stack영역 등으로 나눠서 물리메모리에 저장한다.
세그멘테이션도 페이징과 비슷하게 세그먼트 테이블을 가진다.
페이징 테이블의 경우 페이지 크기가 일정하지만 세그먼트는 크기가 일정하지 않아, limit 정보가 추가로 들어가 있다.
내부단편화는 적지만 외부 단편화가 발생한다.
세그멘테이션 vs 페이징
세그멘테이션은 페이징보다 보호와 공유 면에서는 더 낫다.
세그멘테이션은 read/write/execute 권한을 테이블에 추가하는데, 이때 이것을 논리적으로 나누기 때문에 해당 비트를 설정하기 간단하고 안전하다. 반면, 페이징은 code+data+stack 영역이 존재할 때 이를 일정한 크기로 나누기 때문에 영역이 섞여 비트를 설정하기 까다로워질 수 있다.
공유의 측면에서도 마찬가지로, 페이징은 영역이 섞일 가능성이 존재하지만, 세그멘테이션은 정확히 영역을 나누므로 더 효율적으로 공유를 할 수 있다.
하지만, 현재 대부분은 페이징 기법을 세그멘테이션보다 많이 사용한다.
그 이유는 세그멘테이션의 세그먼트 크기가 일정하지 않고 다양하기 때문이다. 세그먼트의 크기가 다양하기 때문에 다양한 hole이 발생해 외부단편화가 발생하여 메모리 낭비가 크게 된다.
https://code-lab1.tistory.com/57
가상 메모리
배경
메인 메모리의 크기는 한정되어 있다. 따라서 물리적인 메모리 크기보다 크기가 큰 프로세스는 실행시킬 수 없게 된다. 이를 해결하기위해 나온 방법이 가상 메모리이다.
가상 메모리는 메모리 관리 기법의 하나로, 실제로 이용 가능한 자원을 추상화하여 사용자에게 매우 큰 메모리인것처럼 보이게 만드는 것을 말한다. 프로그램에게 실제 메모리 주소가 아닌 가상 메모리의 주소를 주는 방식으로 가상적으로 주어진 주소를 가상 주소, 실제 메모리 상에서 유효한 주소를 물리 주소라고 한다.
가상주소공간은 메모리 관리 장치에 의해 물리 주소로 변환된다.
- 사용자 프로그램이 물리 메모리보다 커져도 된다. 즉 메모리 크기의 제약이 자유로워진다.
- 각 사용자 프로그램이 더 적은 메모리를 차지하여 더 많은 프로그램을 동시에 수행할 수 있다.
- CPU 이용률과 처리율이 높아진다.
- 프로그램을 메모리에 올리고 스왑 하는 필요한 입출력 횟수가 줄어든다.
- 가상 메모리 파일의 공유를 쉽게 하고 공유 메모리 구현을 가능하게 한다.
- 프로세스 생성을 효율적으로 처리할 수 있는 메커니즘을 제공한다
Demand Paging (요구 페이징)
프로세스를 실행할때 해당 영역의 모든 부분이 필요한 것은 아니다. 따라서 실행 시 필요한 부분만 메모리에 올림으로써 메인 메모리에 올라가는 프로세스의 크기를 줄일 수 있다. 당장 실행에 필요한 페이지만 메모리에 적재하는 기법이 요구 페이징이다.
페이지 교체 알고리즘
페이지 교체
페이지를 메모리에 요청하는 과정에서 page fault(페이지 부재)가 발생하게 되면, 원하는 페이지를 보조장치에서 가져오게 된다. 물리메모리가 꽉 찼으면 페이지 교체 작업이 필요하다.
페이지 교체 흐름
- 디스크에서 필요한 페이지의 위치를 찾는다.
- 빈 페이지 프레임을 찾는다.
- ㅍ,레임 테이블을 수정
- 사용자 프로세스 재시작
페이지 교체 알고리즘
[FIFO 페이지 교체]
First-In-First-Out Page Replacement
물리메모리에 들어온 페이지 순서대로 페이지 교체 시점에 먼저 나가게 된다.
장점
단점
- 오래된 페이지가 불필요한 정보를 포함한다고 보장할 수 없다.
- 처음부터 활발하게 사용되는 페이지를 교체해서 페이지 부재율을 높일 수 있다.
- Belady의 모순 : 페이지를 저장할 수 있는 페이지 프레임의 개수를 늘려도 되려 페이지 부재가 더 많이 발생한다는 모순이 존재한다.
[최적 페이지 교체]
Optimal Page Replacement
모든 알고리즘보다 낮은 페이지 부재율을 보이며 Belady의 모순 또한 발생하지 않는다. 이 알고리즘의 핵심은 앞으로 가장 오랫동안 사용되지 않을 페이지를 찾아 교체하는 것이다. 그래서 말그대로 최적 알고리즘 미래 페이지 어떻게 쓸지는 아무도 모름 -> 비교 목적을 위해 사용된다.
장점
단점
- 구현이 어렵다. 모든 프로세스의 메모리 참조 계획을 미리 파악할 수 없기 떄문이다.
[LRU 페이지 교체]
Least-Recently-Used Page Replacement
최적 알고리즘의 근사 알고리즘. 가장 오랫동안 사용되지 않은 페이지를 선택하여 교체한다.
특징
FIFO < LRU < OPT
[LFU 페이지 교체]
Least-Frequently-Used Page Replacement
참조 횟수가 가장 적은 페이지를 교체한다. 활발하게 사용되는 페이지는 참조 횟수가 많아질 거라는 가정에서 만들어졌다.
특징
- 어떤 프로세스가 특정 페이지를 집중적으로 사용하다가 다른 기능을 사용하게 되면 더 이상 사용하지 않아도 계속 메모리에 머물게 되어 초기 가정에 어긋 날 수 있다.
- OPT 알고리즘을 제대로 근사하지 못해 잘 쓰이지 않는다.
캐시의 지역성
캐시 메모리
- 기억장치에서 자주 사용하는 프로그램과 데이터를 저장해두어 속도를 빠르게 하는 메모리
- 그러므로 캐시는 주기억장치보다 크기가 작을 수밖에 없다!
- 캐시 기억장치와 주기억장치 사이에서 정보를 옮기는 것을 사상(Mapping, 매핑)이라고 함
- 매핑의 3가지 방법
- 직접 매핑(Direct Mapping), 연관 매핑(Associate Mapping), 집합 연관 매핑(Set Associate Mapping)
- 속도가 빠른 장치와 느린 장치간의 속도 차에 따른 병목현상을 줄이기 위한 범용 메모리
- 이를 위해서는 CPU가 어떤 데이터를 원하는지 어느 정도 예측할 수 있어야 한다.
- 캐시 메모리에 CPU가 이후에 참조할, 필요 있는 정보가 어느 정도 들어있느냐에 따라 캐시의 성능이 좌우되기 때문
Locality
- 캐시가 효율적으로 동작하려면, 캐시의 적중율(Hit-rate)를 극대화 시켜야 한다.
- 캐시에 저장할 데이터가 지역성(Locality)을 가져야 한다.
- 지역성이란, 데이터 접근이 시간적, 혹은 공간적으로 가깝게 일어나는 것을 의미한다.
- 지역성의 전제 조건으로 프로그램은 모든 코드나 데이터를 균등하게 Access하지 않는다는 특성을 기본으로 한다.
- 즉, 지역성(Locality)이란
- 기억장치 내의 정보를 균일하게 Access하는 것이 아닌 어느 한 순간에 특정 부분을 집중적으로 참조하는 특성이다.
시간적 지역성? 최근에 접근한 데이터가 가까운 미래에 또 접근할 가능성이 높은 것
공간적 지역성? 특정 데이터와 가까운 주소가 순차적으로 접근할 가능성이 높은 것
Caching line
캐시에 데이터를 저장할 때 특정 자료구조를 사용하여 묶음으로 저장하는데, 이를 캐싱 라인(Caching Line)이라고 한다. 빈번하게 사용되는 데이터의 주소들이 흩어져 있기 때문에 캐시에 저장하는 데이터에는 데이터의 주소 등을 기록해둔 태그를 달아둘 필요가 있다. 이러한 태그들의 묶음을 의미한다.
https://chelseashin.tistory.com/43