파일 단위
로 저장 장치
에 저장되어 있으며, 아직 실행되지 않은 상태의 코드 덩어리
프로세스는 운영체제로부터 메모리 공간을 할당 받아 실행 중인 프로그램
- 코드, 데이터, 힙, 스택
코드 영역
프로세스가 실행할 코드
가 기계어
의 형태로 저장컴파일 타임
에 결정 Read-Only
데이터 영역
컴파일
타임에 결정, Read-Wirte
: 실행 중 변경가능힙 영역
런타임
에 결정낮은 주소에서 높은 주소
로 할당스택
컴파일
타임에 결정높은 주소에서 낮은 주소
로 할당힙만 런타임에 결정된다.
초기화 된 변수: Data 영역, 초기화하지 않은 변수: BSS
Stack과 Heap 공간 접근 속도
- 스택이 훨 빠름: 이미 할당되어 있는 공간 사용
- 스택할당: 이미 생성되어 있는 스택에 포인터 위치만 바꿔주는 단순 CPU 연산
- 힙은 사용자가 할당해서 사용
- 요청된 chuck의 크기, 현재 메모리의 fagmentation 상황 등 다양한 요소를 고려하기 때문에 더 많은 CPU 연산 필요
공간 분할 이유?
- 최대한 데이터를 공유하여 메모리 사용량을 줄이기 위해서
- 같은 프로그램을 띄울 때 code영역 공유 가능
- Stack, Data 영역을 나눈 이유? 역할 분배
- stack: 함수의 흐름 관리
- data: 전역변수, 정적 변수를 관리
같은 프로세스 내 다른 스레드와 메모리 영역 공유
고유한 스레드 ID
, 프로그램 카운터(PC)
, 레지스터 집합
, 스택 영역
을 가진다.속한 프로세스 내
의 코드, 데이터, 힙 영역
과 기타 운영체제 자원(열린 파일, 신호 등)
다른 스레드와 공유독립적인 스택 / 코드,데이터,힙 공유
각 스레드는 스택을 통해 독립적인 실행 흐름을 가진다.
🌈🌈스레드는 프로세스 메모리 영역을 공유하기 때문에 어떤 스레드 하나에 오류가 발생하면 같은 프로세스 내의 다른 스레드 모두 강제 종료
🌈🌈프로세스는 한 프로세스가 강제 종료되어도 공유 자원을 손상시키는 경우가 아니라면 다른 다른 프로세스에게 영향을 주지 않는다.
멀티 프로세서나 멀티 코어 구조가 발전하기 전에는 싱글 프로세서로 재빠르게 프로세스를 전환하여 concurrent하게 동작하지만 parallel하게 동작하는 것처럼 보이도록 함
CPU 코어를 다른 프로세스로 전환한기 위해 현재 프로세스의 상태 저장 및 다른 프로세스의 상태 복원
스레드와 프로세스 중 컨텍스트 스위칭이 빠른 것은
스레드
- 스레드는 stack을 제외한 프로세스 메모리 영역을 공유하기 때문에 자신의 PCB에는 스택 및 간단한 정보만 저장하기 때문에 더 빠르다.
- 프로세스는 공유하는 데이터가 없으므로 임시 저장소인 캐시 메모리가 지금껏 쌓아놓은 데이터들이 사라지고 새로 데이터를 쌓아야 한다.
컨텍스트 스위칭이 발생할 때
인터럽트(Interrupt)
- 입/출력을 요청할 때
- CPU 사용시간이 만료되었을 때
- 자식 프로세스를 만들 때
- 인터럽트 처리를 기다릴 때
여러 개의 프로세스를 동시에 수행하는 것
프로세스는 부모, 자식 관계라고 해도
자신만의 메모리 영역
을 가지게 되며,공유되는 메모리 영역 없이 독립적
인 구조를 가진다.
대부분의 브라우저는 탭 브라우징을 지원한다.
만일 브러우저가 멀티 프로세스 구조를 가지지 않는다면 어떤 탭의 웹 어플리케이션이 비정상 종료되었 때, 다른 모든 탭을 포함한 전체 프로세스가 종료 될 것이다.
구글의 크롬 브라우저는 멀티 프로세스 구조를 가지고 있다. 브라우저의 각 탭은 Renderer 프로세스이며, 이들은 각자 독립적으로 실행된다. 하나의 웹사이트가 비정상 종료되어도 다른 Renderer 프로세스는 영향을 받지 않는다.
크롬은 다음과 같은 3가지 유형의 프로세스를 지원한다.
브라우저 프로세스: 사용자 인터페이스와 디스크 및 네트워크 I/O를 관리한다. 크롬이 시작되면 새 브라우저 프로세스가 생성
Renderer 프로세스: 웹 페이지 렌더링을 위한 로직(HTML, JavaScript, 이미지 등 처리)을 포함한다.
플러그인 프로세스: 각 플로그인 유형에 대해 플로그인 프로세스가 생성된다. 플러그인 프로세스에는 플러그인에 대한 코드와 연관된 Renderer, 브라우저 프로세스와 통신할 수 있는 추가 코드가 포함되어 있다.
독립적인 메모리 영역을 가지는 프로세스끼리 통신하는 방법
데이터를 교환하기 위해서 IPC(Inter-Process Communication) 매케니즘이 필요하다.
파이프
소켓
메세지 큐
메모리 맵
한 프로세스에서 여러 개의 스레드를 동시에 수행하는 것
웹 서버 프로세스는 클라이언트 요청이 들어오면 그 요청을 처리하기 위한 별도의 스레드를 생성
한다.응답성
이 좋아진다.자원을 공유
할 수 있다.비용이 적
다.스레드 생성과 context swtiching 비용이 더 적
다.프로세스 스케줄러는 멀티 프로그래밍과 time sharing의 목적을 달성하기 위해 실행 가능한 여러 프로세스 중에서 하나의 프로세스를 선택해 실행한다.
각 CPU 코어는 한번에 한 프로세스를 실행할 수 있다.
단일 CPU 코어 시스템에 반해 멀티 코어 시스템은 한 번에 여러 프로세스를 실행할 수 있다.
멀티 포르그래밍: CPU 사용률을 최대화하기 위해 항상 프로세스를 실행하도록 한다. 어떤 프로세스가 CPU를 사용하다가 I/O 작업 등 CPU를 필요로 하지 않는 순간이 오면 다른 프로세스가 CPU를 사용할 수 있도록 한다.
시분할 (time sharing) : 각 프로그램이 실행되는 동안 사용자들이 상호작용할 수 있도록 프로세스 간 CPU 코어를 자주 전환하는 것이다. CPU가 하나의 프로그램을 수행하는 시간을 매우 짧은 시간(ms)으로 제한하여 프로그램을 번갈아 수행하도록 하면 CPU가 하나인 환경에서도 여러 사용자가 동시에 사용하는 듯한 효과를 가져올 수 있다.
New : 프로세스가 생성됨
Running : 프로세스의 Instruction이 실행됨
Waiting : (I/O 작업 완료나 신호 수신과 같은) 이벤트가 발생하기를 기다림
Ready : 프로세서에 할당되기를 기다림
Terminated : 프로세스가 실행을 끝냄
Ready Queue
Wait Queue
프로세스는 종료될 때까지 위의 Queueing-diagram과 같은 주기를 반복하고, 종료되면 모든 큐에서 제거되고 PCB 및 자원 할당이 해제된다.
CPU 스케줄링은 Ready Queue에 있는 프로세스들을 대상
스케줄링 시 상황 1, 4에서는 선택권 없이 새 프로세스를 선택해야 한다. 하지만 상황 2, 3에서는 다음과 같은 선택권이 있다.
비선점 스케줄링 : CPU가 할당된 어떤 프로세스는 종료 / waiting 상태로 전환하여 CPU를 해제할 때까지 CPU를 유지하고, 다른 프로세스는 그 때까지 CPU를 사용할 수 없다.
선점 스케줄링 : 어떤 프로세스가 CPU를 점유하고 있을 때 다른 프로세스가 CPU를 선점할 수 있다. Windows, macOS, Linux 및 UNIX를 포함한 거의 모든 최신 운영체제는 선점 스케줄링 알고리즘을 사용한다.
비선점 스케줄링
먼저 CPU를 요청하는 프로세스에 먼저 CPU가 할당된다.
FIFO queue 를 사용해 쉽게 구현할 수 있다.
문제점) convoy effect
비선점 스케줄링 방식
선점 스케줄링 방식 (SRTF (Shortest-Remaining-Time-First) Scheduling)
Priority Scheduling의 한 예이다. (우선순위 = CPU burst time)
주어진 프로세스 집합에 대해 최소 평균 대기 시간
을 제공한다는 점에서 최적의 알고리즘이다.
하지만 CPU burst time을 알 수 있는 방법이 없기 때문에 CPU 스케줄링 수준에서 구현할 수 없다.
문제점) starvation
선점 스케줄링
각 프로세스는 time quantum (or time slice) 이라는 작은 시간 단위(10-100ms)를 갖게 된다.
프로세스는 1 time quantum 동안 스케줄러에 의해 CPU를 할당 받고, 시간이 끝나면 interrupt를 받아 Ready Queue의 tail에 배치된다.
Ready Queue는 Circular FIFO queue 형태
RR의 평균 대기 시간은 긴 편이다. 하지만 공정하다.
n개의 프로세스가 있고 time quantum이 q일 때, 어떤 프로세스도 (n-1) x q 시간 단위 이상 기다리지 않는다.
Time quantum 설정 시 주의할 점
- Time quantum이 너무 크다면 : FCFS와 같아진다.
- Time quantum이 너무 작다면 : Context Switching이 너무 빈번하게 일어나 overhead가 발생한다.
위와 같이 RR 알고리즘의 성능은 time quantum의 크기에 좌우될 수 있으므로 적절히 선정해야 하며 이는 context-switch time보다 큰 것이 좋지만 또 너무 커서는 안 된다. (경험적으로 CPU burst의 80프로는 time quantum보다 짧은게 좋다고 함)
선점 / 비선점 스케줄링 모두 가능하다.
- 선점 방식 : 새로 도착한 프로세스의 우선 순위가 현재 실행 중인 프로세스의 우선 순위보다 높으면 CPU 선점
- 비선점 방식 : 같은 경우 단순히 새 프로세스를 Ready Queue의 맨 앞에 둔다.
문제점) indefinite blocking, starvation
해결 방안) Aging, Round-Robin과 결합
Synchronous == Blocking ? Asynchronous == Non-blocking?
결론 부터 말하자면 다르다!
동기와 비동기는
호출 되는 함수의 완료
를 호출한 쪽에서 신경 쓰느냐 호출 받은 쪽에서 신경을 쓰냐의 차이
Blocking 호출받은 쪽이 호출한 쪽에 제어권을 넘겨주지 않는 것이고 Non-blocking은 다시 제어권을 넘겨주는 것
가장 기본적으로 생각하는 Sync 이다. 함수를 호출하면 호출 받은 쪽에서 제어권을 가지고 있기 때문에 결과값이 반환 될때 까지 다음 동작을 시행 하지 않는다.
Non-Blocking 이라 함수가 완료 되지 않아도 제어권은 넘겨 주어 함수를 호출한 쪽에서 다음 동작을 시행 할 수는 있지만 함수가 완료되는 것을 신경을 써야하기 때문에 주기적으로 함수가 완료 되었는지 확인 해야한다.
잘 상상이 안 가는 그림이다. 작업완료 여부를 호출된 쪽에서 신경 쓰고 제어권도 호출된 쪽에서 가지고 있다. 사실상 Sync & Blocking과 거의 같아 잘 사용되지 않는다.
가장 기본적으로 생각하는 Async이다. 함수를 호출하면 제어권을 다시 호출 한쪽으로 넘겨주어 다음 동작을 이어 나가면서 호출 받은 쪽에서 알아서 콜백 함수의 결과를 리턴하여준다.
네 가지 조합의 모든 경우의 수가 가능하다고 하는데 잘 이해가 안된다. 다음에 다시 보기로!!!
참고
https://github.com/Seogeurim/CS-study/tree/main/contents/operating-system#priority-scheduling
동일한 자원을 동시에 접근하는 작업을 실행하는 코드영역
멀티 쓰레딩의 문제점이 발생
공통된 (data) 영역에 하나의 프로세스(task or thread) 만 들어 갈 수 있도록 설계하는 것
Acquire() : Lock 획득
Release() : Lock 방출
Task가 Crtical Section에 들어갈 때 acquire() 하고 나올 때 release() 하여 한 Task만 Critical Section 에 들어 갈 수 있게 한다.
while(true){
acquire();
/* Critical Section*/
release();
/* Remainder Section*/
}
acquire(){ // 사용가능 해지면 크리티컬 섹션에 들어간후 문을 잠금!
while(!available) // Busy Waiting
available = false;
}
release(){ // 사용가능 하게 해줌
available = true;
}
문제점 : Busy waiting(spin lock) 으로 인해 효율이 떨어진다.
Semaphore
는 Critical Section에 들어갈 수 있는 task의 수
이다. 자원의 갯수가 여러개라고 생각하는 것이 편하다. 따라서 Critical Section에 상호 배타적으로 들어 갈 수 있는 것이다.Semaphore s // Integer Value & Positive #
- Busy Waiting 을 사용하는 Semaphore
wait(s){ while(s <= 0){} // busy waiting s-- } signal(s){ s++ }
- s 값이 양수여야지만 Critical Section에 들어가 작업을 수행 할 수 있음.
- Busy waiting을 사용하는 구현은 Critical Section 은 있지만 사용하고자 하는 Task의 수가 적을 때 사용함.
- Busy Waiting 을 사용하지 않는 Semaphore
// waiting queue를 사용 wait(s){ s--; if(s < 0){ // s < 0 이면 s의 절댓값 만큼 waiting queue에서 Task 대기중 // waiting queue에 task t 를 집어넣음 block(); } } signal(s){ s++; if(s <= 0){ // waiting queue에서 대기중인 task 존재 // waiting queue에서 task t 를 제거 wakeup(t); } }
Mutex Lock은 Lock을 갖고 있는 thread가 해제
가능한 반면, Semaphore는 외부에서도 해제
가능Semaphore는 시스템 범위에 걸쳐
져 있고 파일형태
로 존재하는 반면, Mutex Lock은 프로세스 범위 내
에 잇어서 종료시 자동으로 clean up
되어짐교착상태가 발생하기 위해서는 다음의 네 가지 조건이 충족되어야 하는데, 하나라도 충족되지 않으면 교착상태가 발생하지 않는다.
- 상호배제(Mutual Exclusion) : 한 번에 한 개의 프로세스만이 공유 자원을 사용할 수 있어야 한다.
- 점유와 대기(Hold and Wait) : 최소한 하나의 자원을 점유하고 있으면서 다른 프로세스에 할당되어 사용되고 있는 자원을 추가로 점유하기 위해 대기하는 프로세스가 있어야 한다.
- 비선점(Non-preemption) : 다른 프로세스에 할당된 자원은 사용이 끝날 때까지 강제로 빼앗을 수 없어야 한다.
- 원형 대기
교착상태가 발생하지 않도록 사전에 시스템을 제어하는 방법으로, 교착상태 발생의 네 가지 조건중에서 어느 하나를 제거하는 방법이다. 자원 낭비가 가장 심한 기법이다.
- 상호 배제 부정 : 한 번에 여러개의 프로세스가 공유 자원을 사용할 수 있게 한다.
- 점유 및 대기 부정 : 프로세스가 실행되기 전 필요한 모든 자원을 할당하여 프로세스 대기를 없애거나, 자원이 점유되지 않은 상태에서만 자원을 요구한다.
- 비선점 부정 : 자원을 점유하고 있는 프로세스가 다른 자원을 요구할 때 점유하고 있는 자원을 반납하고, 요구한 자원을 사용하기 위해 기다리게 한다.
- 원형 대기 부정 : 자원을 선형 순서로 분류하여 고유번호를 할당하고, 각 프로세스는 현재 점유한 자원의 고유 번호보다 앞이나 뒤 어느 한쪽 방향으로만 자원을 요구한다.
교착상태가 발생할 가능성을 배제하지 않고, 교착상태가 발생하면 적절히 피해나가는 방법으로, 은행원 알고리즘
(Banker's Algorithm) 이 사용된다.
- 은행원 알고리즘은 다익스트라가 제안한 기법으로, 은행에서 모든 고객의 요구가 충족되도록 현금을 할당하는데서 유래한 기법
- 각 프로세스에게 자원을 할당하여 교착상태가 발생하지 않으며, 모든 프로세스가 완료될 수 있는 상태를 안전 상태(safe state)라고 하며, 교착상태가 발생할 수 있는 상태를 불안전 상태(unsafe state)라고 함
- 은행원 알고리즘을 적용하기 위해서는 자원의 양과 프로세스 수가 일정해야 함
- 은행원 알고리즘은 프로세스의 모든 요구를 유한한 시간안에 할당하는 것을 보장함
시스템에 교착상태가 발생했는지 점검하여 교착상태에 있는 프로세스와 자원을 발견하는 기법이다. 발견 후엔 교착상태 회복(Recovery) 직업을 수행하므로 발견기법과 회복기법을 함께 쓴다. (Detection & Recovery)
교착상태를 일으킨 프로세스를 종료하거나, 교착상태의 프로세스에 할당된 자원을 선점하여 프로세스나 자원을 회복하는 것을 의미한다. 크게 프로세스 종료와 자원 선택으로 나뉜다.
- 프로세스 종료
프로세스 하나를 임의로 종료하여 교착상태를 해결하는 방법이다. 두 가지의 방법을 사용할 수 있다.
- 자원 선점
교착상태가 깨질 때까지 프로세스로부터 자원을 계속적으로 선점해 다른 프로세스에게 주어야 한다. 따라서 다음 사항들을 꼭 고려해야 한다.