시스템의 자원과 동작을 관리하는 소프트웨어 이며,
프로세스, 저장장치, 네트워킹, 사용자, 하드웨어 등을 관리하게 됩니다.
- 전처리기 치환 (#include, define 등)
- 컴파일러
- 소스코드를 어셈블리 코드로 번역합니다.
- 어셈블리 코드는 CPU에게 일을 시킬 수 있는 명령어의 조합입니다.
- 바이너리 코드 생성
- 2단계를 거친 어셈블리 코드를 어셈블러에 의해 바이너리 코드(기계어)로 변환시킵니다.
- 기계만이 CPU에 명령내릴 수 있기 때문입니다.
- 링커에 의한 연결과 결합
- 링커가 생성한 코드에서 참조하는 라이브러리들을 하나로 묶는 작업을 합니다.
- 즉, 바이너리 코드에서 사용되는 라이브러리 함수들을 포함시키는 작업
- 이 과정이 끝나면 실행파일이 생성됩니다.
- 실행파일이 실행되면 실행파일을 구성하는 바이너리 코드가 메인 메모리에 올라가서 CPU가 순차적으로 실행시킵니다.
로더(Loader)에 의해 코드가 메모리에 적제되고 실행됩니다.
- Loading 단계
하드드라이브에 있는 실행 프로그램을 메모리에 올립니다.- Fetch 단계
메모리에 올라온 실행 프로그램을 CPU의 레지스터(명령어를 임시로 저장하는 곳)에 올립니다.- Decode 단계
ALU (CPU의 연산하는 단계)에서 연산하기 전, 레지스터의 명령어를 CPU의 제어장치에서 해독합니다.- 실행(Execution) 단계
해독된 명령어들을 ALU에서 연산합니다.
캐시 메모리(이하 캐시)란 데이터를 미리 복사해두는 임시 저장공간을 말합니다. Cache는 저장 공간이 작고 비용이 비싼 대신 빠른 성능을 제공합니다.
모든 데이터를 Cache에 담기에는 저장공간이 너무나도 작습니다. 그렇기 때문에 소수의 데이터를 선별해야합니다. 이때 사용되는 것이 지역성입니다.시간 지역성
특정 데이터가 한 번 접근되었을 경우 가까운 미래에 또 한번 데이터에 접근할 가능성이 높은 것을 말합니다.공간 지역성
특정 데이터와 가까운 주소가 순서대로 접근되었을 경우를 공간적 지역성이라고 합니다.순차 지역성
공간 지역성과 함께 설명되기도 합니다. 데이터가 순차적으로 엑세스되는 경향을 보이며 프로그램 내의 명령어가 순차적으로 구성되는 특성이 있습니다.
캐시에 데이터를 저장할 때, 특정 자료구조를 사용하여 묶음으로 저장하게 되는 방법입니다.
메모리에는 총 4가지의 구조가 있습니다.
구조는 Code, Data, Heap, Stack 으로 구성되어 있습니다.
Code는 소스코드가 들어가는 부분이고,
Data는 전역변수, 정적변수가 할당되는 부분입니다.
그리고,
Heap은 사용자가 직접 관리하는 영역으로 데이터가 동적으로 할당되는 공간입니다.
마지막으로 Stack은 함수의 호출정보, 지역변수, 매개변수들이 저장되게 됩니다.
같은 점은,
둘 다 프로세스가 죽을 때까지 유지되기 때문에 초기화가 필요하다는 것이고,
다른점은,
전역변수는 해당 프로그램(실행파일 기준)의 어느 함수, 어느 파일에서도 접근이 가능한 반면, 정적변수는 변수가 선언된 파일이나 함수내에서만 접근이 가능합니다.
스택은 정적 메모리 구조를 가지고 힙 영역은 동적 메모리 구조를 가집니다.
스택영역은,
- 함수 내에 정의된 지역 변수와 매개변수 등이 저장됩니다.
- 메소드 호출시 마다 각각의 스택프레임(그 메서드 만을 위한 공간)이 생성됩니다.
- 메소드 수행이 끝나면 프레임 별로 삭제됩니다.
- 프로그램에서 함수는 다른 함수를 호출하고 그 결과를 자신을 호출한 함수에 반환해줍니다.
- 따라서, 스택구조로 함수의 호출이 차곡차곡 메모리에 쌓이고 처리가 끝나면 메모리에서 해제됩니다.
- 이렇게 스택의 구조를 활용하여 함수의 지역 변수 메모리를 관리하면 위의 메커니즘을 쉽게 구현 할 수 있기 때문에 스택 형태로 영역을 만들어 활용합니다.
- 스택영역 (스택 세그먼트) 라고 부릅니다.
힙 영역은,
- 관리가 가능한 데이터 외에 다른 형태의 데이터를 관리하기 위한 빈공간(Space) 입니다.
- 즉, 동적할당(Dynamic Allocation)에 의해 생성된 동적 변수(Dynamic Variables)를 관리하기 위한 영역입니다.
- 자바에서 new연산자로 생성된 객체와 배열을 저장하는 공간입니다.
- 클래스 영역에 로드된 클래스만 생성 가능합니다.
- GC(GarbageCollector)를 통해 메모리 반환합니다.
- java나 c++등에서 'new', c에서 'malloc', 'calloc' 을 통해 동적으로 생성되는 변수를 저장하기 위해 할당 되는 영역입니다.
가시성은,
하나의 변수를 변경한다고 했을 때 다른 사용자에게 이것이 제대로 보여지냐에 대한 것입니다.성능상의 이유로 스레드들은 각각 할당받은 CPU의 Cache Memory를 이용하게 되는데 이곳에 저장된 연산의 결과가 언제 Main Memory로 올라갈지 모른다고 한다. 이에 대한 예시를 들면 아래와 같습니다.
- counter 변수의 값을 증가시키는 연산을 Thread1과 Thread 2가 수행한다.
- Thread1의 연산으로 counter 변수의 값이 7이 되었다 가정했을 때, 그 결과는 CPU1의 Cache Memory에 적재되어 있다.
- Thread 2의 연산 차례가 와서 Main Memory에 있는 counter 값을 CPU2의 Cache Memory로 가져와 연산을 수행한다. 이때의counter 값은 Thread1의 결과가 아직 Main Memory에 올라가지 않았기에 0이며, Thread1의 연산 결과가 7이라는 사실을 Thread 2는 알 수 없다.
- 이것을 비가시성이라 한다.
이로 인해 counter 변수에 대한 값의 불일치가 발생하고 우리는 원하는 결과를 얻을 수 없게 됩니다. 그러나 Volatile 키워드를 사용하게 되면, Thread1의 결과가 CPU1의 Cache Memory에 저장되었다가 Main Memory에 적재되는 게 아닌, 바로 Main Memory에 적재되기 때문에 Thread 2가 읽은 값은 Thread1의 결괏값이 될 것입니다.
원자성은,
여러 줄의 코드가 하나의 단계처럼 동작하여 중간에 다른 사용자의 접근을 막을 수 있고 중간에 오류 발생시 변경사항 전체를 되돌릴 수 있습니다. - 이건 데이터베이스에 대한 원자성인 것 같습니다.
유효주소란,
데이터가 저장된 메모리의 실제 주소를 의미합니다. CPU는 유효주소를 통해서 메모리에 접근하게 됩니다.주소지정방식이란,
유효주소를 저장하는 방식이며, 직접주소 지정방식과 간접주소 지정방식이 있습니다.직접주소 지정방식이란,
유효주소가 주소란에 바로 들어가 있어서 바로 접근할 수 있는 방식입니다.
간접주소 지정방식이란,
주소로 바로 접근하는게 아닌 주소를 따로 저장한 뒤에 그 따로 저장된 주소를 통해서 유효주소로 접근하는 방식입니다.
메모리 단편화를 줄이기 위해 세그먼트 기법으로 메모리를 할당을 할때 사용하는 알고리즘입니다.
해당 알고리즘에는 first fit, Best fit, Worst fit 이 있습니다.
first fit,
메모리의 처음부터 끝까지 순서대로 보다가 할당한 프로세스 크기에 맞는 공간이 있으면, 해당 메모리 위치에 할당하는 방식입니다.
(뒷 순서에 해당 프로세스를 할당하기 좋은 영역이 있더라도, 순서대로 가장 먼저 찾은 곳에 바로 할당합니다.
Best fit,
메모리의 처음부터 끝까지 확인 후, 순서가 아닌 해당 프로세스 크기에 가장 적합한 (가장 작은) 공간에 할당합니다. first fit에 비해 메모리는 절약할 수 있어도 모든 메모리 영역을 확인하기 때문에, 처리속도는 늦습니다.
worst fit,
메모리의 전체 공간 중 가장 큰 영역에 할당하는 방식입니다. 이렇게 하는 이유는, 가장 넓은 영역에 가장 작은 프로세스부터 차곡차곡 쌓아 넣을 목적으로 사용하기 위해서 입니다.
프로세스는 실행 중인 프로그램이고,
스레드는 프로세스 안에서 실행되는 흐름 단위 입니다.
프로세스는 메모리와 CPU를 프로세스마다 할당받아서 사용하는데,
스레드는 프로세스 안에서 다른 스레드와 메모리와 CPU를 공유해서 사용합니다.
멀티 프로세스
- 하나의 응용 프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 처리하는 것
- 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽어 다른 영향이 확산되지 않음
멀티 스레드
- 하나의 응용 프로그램을 여러 개의 쓰레드로 구성하고 각 쓰레드가 하나의 작업을 처리하는 것
- 시스템 자원 소모 감소
- 시스템 처리량 증가
- 다른 프로세스에서 쓰레드를 제어할 수 없다.
멀티 프로세스 대신 멀티 쓰레드를 사용하는 이유
- 자원의 효율성 증대
프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어서 자원 관리가 효율적- 처리 비용 감소 및 응답 시간 단축
프로세스 간의 통신 보다 쓰레드 간의 통신 비용이 적다.
Process를 새로 생성하거나 제거하는 것이 Thread를 새로 생성하거나 제거하는 것 보다 오래 걸립니다.
- Process간의 context switching이 Thread간의 context switching보다 오래 걸림.
준비큐에 있는 프로세스에 대해서 CPU를 할당하는 방법입니다.
크게 다섯가지가 있는데요.
FCFS, SJF, SRT, 우선순위 스케줄링(Priority Scheduling), Round Robin 이 있습니다.
- FCFS(First Come First Served)는 가장 먼저 요청한 프로세스 순서대로 처리하는 방식입니다.
- SJF(Shortest Job First)는 평균 대기시간을 최소화하기 위해 사용하는 방식으로, 처리시간이 짧은 프로세스 부터 CPU를 할당합니다.
- SRT(Shortest Remaining Time)는 가장 짧은 잔여시간이 요구되는 프로세스를 우선으로 하는 스케줄링으로, 진행 중인 프로세스가 있어도 더 짧은 잔여시간인 프로세스를 위해 sleep 시키고 짧은 프로세스를 먼저 할당합니다.
- RR(Round Robin)은 시간 공유 시스템을 위해 설계된 스케줄링으로, 모든 프로세스가 같은 우선순위를 가지고, time slice 기반으로 스케줄링 합니다. 설정한 time slice 마다 프로세스를 공평하게 할당합니다. 다만, time slice를 너무 길게 설정하면 fcfs와 다를게 없습니다. 그리고 time slice 마다 다른 프로세스에 CPU가 할당될때마다 프로세스 전환비용이 발생하여, time slice를 너무 작게 설정하면 전환비용 때문에 비효율적인 스케줄링이 됩니다. 위 경우 때문에 적정한 time slice를 설정해야 합니다.
- 우선순위 스케줄링은, 우선순위가 높은 프로세스에 CPU를 우선 할당하는 방식이며 시간제한, 메모리 요구량, 프로세스 중요성, 자원사용 비용 등에 따라 달라질 수 있습니다. 만약 우선순위가 동일할 경우 FCFS와 다를 것이 없습니다.
(비선점, 선점 둘다 사용된다.)
스레싱(thrashing)은 하드디스크의 입출력이 너무 많아져서 잣은 페이지 부재로 마치 작업이 멈춘 것 같은 상태를 말합니다.
IPC는 프로세스들 사이에 서로 데이터를 주고 받는 방식, 즉 프로세스 간의 통신을 의미합니다. 각 프로세스는 독립적인 실행 객체이기 때문에 프로세스 간 통신을 하려면 커널이 제공하는 IPC 모델 방식을 사용해서 통신을 해야 합니다.
커널은 OS의 모든 부분에 대한 기본 서비스를 제공하는 컴퓨터 운영 체제의 핵심이자 가장 중요한 부분이며 컴퓨터에 속한 자원들에 대한 접근을 중재합니다.
여러 프로세스 및 스레드가 공유 자원에 동시 접근 시 그 순서에 따라 결과가 달라지는 문제입니다.
커널 레벨 쓰레드와 유저 레벨 쓰레드는 생성 주체가 누구냐에 따라 구분됩니다.
프로그래머 요청에 따라 쓰레드를 생성하고 스케줄링하는 주체가 커널이면 커널 레벨(Kernel Level) 쓰레드 입니다.
커널 레벨 쓰레드의 장점은,
- 커널이 직접 제공해 주기 때문에 안정성과 다양한 기능이 제공됩니다.
커널 레벨 쓰레드의 단점은,
- 유저 모드에서 커널 모드로의 전환이 빈번하게 이뤄져 성능 저하가 발생합니다.
커널이 쓰레드 모델을 지원하지 않거나 제공하는 쓰레드 모델이 마음에 들지 않을 경우, 커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용할 수 있는데, 이러한 방식으로 제공되는 쓰레드가 유저 레벨(User Level) 쓰레드 입니다.
유저 레벨 쓰레드의 장점은,
- 커널은 쓰레드의 존재조차 모르기 때문에 모드 간의 전환이 없고 성능 이득이 발생합니다.
유저 레벨 쓰레드의 단점은,
- 하나의 스레드가 커널에 의해 블로킹 되면 프로세스 전체가 블로킹되고, 이를 해결하려면 프로그래밍이 어려워지고 커널 레벨 쓰레드에 비해 결과 예측이 어려워집니다.
모든 프로세스에 메모리를 할당하기에는 메모리의 크기에 한계가 있어서 사용하는 방법입니다.
프로세스에서 사용하는 부분만 메모리에 올리고, 나머지는 디스크에 보관하는 기법을 가상메모리라고 합니다.
RAM에서 메모리의 공간이 작은 조각으로 나뉘어져 사용가능한 메모리가 충분히 존재하지만 할당(사용)이 불가능한 상태를 말합니다.
내부 단편화와 외부 단편화로 구분됩니다.내부 단편화(Internal Fragmentation)란,
메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비 되는 상황을 내부 단편화라고 합니다.외부 단편화(External Fragmentation)란,
메모리가 할당되고 해제되는 작업이 반복될 때 작은 메모리가 중간중간 존재하게 됩니다.
이 때 중간중간에 생긴 사용하지 않는 메모리가 많이 존재해서 총 메모리 공간은 충분하지만 실제로 할당할 수 없는 상황을 외부 단편화라고 합니다.
사용하지 않는 프레임을 페이지에 옮기고, 필요한 메모리를 페이지 단위로 프레임에 옮기는 기법입니다.
- 페이징 기법을 사용하면 연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제를 해결할 수 있습니다.
- 페이지 단위를 작게하면 내부 단편화 문제도 해결할 수 있겠지만 대신 page mapping 과정이 많아지므로 오히려 효율이 떨어질 수 있습니다.
세그먼트들의 크기가 다르기 때문에 미리 분할해 둘 수 없고 메모리에 적재될 때 빈 공간을 찾아 할당하는 기법입니다.
- 페이징 기법은 가상메모리를 같은 크기의 단위로 분할했지만 세그멘테이션 기법은 가상메모리를 서로 크기가 다른 논리적 단위인 세그먼트로 분할해서 메모리를 할당하여 실제 메모리 주소로 변환합니다.
- 프로세스가 필요한 메모리 만큼 할당해주기 때문에 내부단편화는 일어나지 않으나 여전히 중간에 프로세스가 메모리를 해제하면 생기는 구멍, 즉 외부 단편화 문제는 여전히 존재합니다.
필요한 메모리 공간을 필요한 크기, 개수만큼 사용자가 직접 지정하여 미리 할당받아 놓고 필요할 때마다 사용합니다.
외부/내부 단편화는 모두 일어나지 않지만, 메모리가 메모리 낭비량보다 커졌을 때는 단점이 됩니다.
페이지 부재 발생 시 새로운 페이지를 할당하기 위해 현재 할당된 페이지 중 어느 것과 교체할 지를 결정하는 전략입니다.
대표되는 교체 알고리즘 종류는,
- FIFO : First-In, First-Out. 메모리에 올라온 지 가장 오래된 페이지를 교체
- 최적 페이지 교체 : Optimal Page Replace. 이론상 최적 알고리즘
- NRU 페이지 교체 : Not-Recently-Used. 최근 미사용 페이지 교체
- LRU 페이지 교체 : Least-Recently-Used. 가장 오래 사용되지 않은 페이지 교체
- LFU 페이지 교체 : Least-Frequently-Used. 참조 횟수가 가장 작은 페이지를 교체
- MFU 페이지 교체 : Most-Frequently-Used. 참조 횟수가 가장 많은 페이지를 교체
CPU에 코드 실행 시, 가상 주소 메모리 접근이 필요할 때, 해당 주소를 물리 주소값으로 변환해주는 하드웨어 장치입니다.
MMU 내부에 있는 캐시 메모리로, 자주 사용하는 메모리 주소에 대한 물리 주소 정보가 저장되어 있습니다.
- 프로세스에 대한 내부 테이블을 검사해서 그 메모리 참조가 유효(valid)/무효(invalid) 인지를 알아낸다.
- 만약 무효한 페이지에 대한 참조라면 그 프로세스는 중단된다.
만약 유효한 참조인데 페이지가 아직 메모리에 올라오지 않았다면, 그것을 디스크로부터 가져와야 한다.- 빈 공간 즉, 자유 프레임을 찾는다. (예를 들면, 페이지 프레임 리스트에서 하나 가져옴)
- 디스크에 새로이 할당된 프레임으로 해당 페이지를 읽어 들이도록 요청한다.
- 디스크 읽기가 끝나면, 이 페이지가 이제는 메모리에 있다는 것을 알리기 위해 페이지 테이블을 갱신하며,
프로세스가 유지하고 있는 내부 테이블을 수정한다.- 트랩에 의해 중단되었던 명령을 다시 수행한다.
이제 프로세스는 마치 그 페이지가 항상 메모리에 있었던 것처럼 해당 페이지를 접근할 수 있다.
프로그램을 실행하는 도중에 예기치 않은 상황이 발생한 경우, 현재 실행중인 작업을 즉시 중단하고, 발생된 상황을 우선 처리한 후 실행중이던 작업으로 복귀하여 계속 처리하는 것 입니다.
시스템콜은 커널과 사용자 사이의 인터페이스 역할을 하는 것으로 쉘(Shell)에서 명령어나 서브루틴 형식으로 운영체제의 기능을 호출할 수 있습니다. 즉, 사용자가 직접 커널에 접근할 수 없기 때문에 시스템콜을 활용해야한다.
보통 시스템 콜을 직접 사용하기보다는, 해당 시스템 콜을 사용해서 만든 각 언어별 라이브러리(API)를 사용합니다.
쉽게 말하면 운영체제의 기능을 호출하는 함수입니다.
fork()는,
부모프로세스의 메모리를 복사하여 사용합니다.
vfork()는,
부모프로세스와의 메모리를 공유하고 복사하지 않기때문에 fork()보다는 생성 속도가 빠릅니다. 하지만 자원을 공유하기 때문에 자원에 대한 경쟁상태(race condition)가 발생하지 않도록 해주기 위해서 부모 프로세스는 자식프로세스가 exit 하거나 execve가 호출되기 전까지 block 됩니다.
시스템 콜은,
사용자(프로그램)가 운영체제에게 무언가를 요청하는 행위입니다.
사용자가 바로 커널을 조작하는 행위는 위험하기 때문에 중간에 System Call Interface라는 부분을 둬서 사용자가 System Call를 통해 커널에 요청을 보내도록합니다. API라고도 합니다.(ex- Win32 API)
블록킹은,
- 호출된 함수가 자신의 작업을 모두 끝낼때까지 제어권을 가지고 있어 호출한 함수가 대기하도록 만듭니다.
- 클라이언트가 I/O 작업을 진행하면 해당 프로세스가 진행하는 작업이 중지됩니다.
- 다른 클라이언트에 영향을 미치지 않게 하기 위해 클라이언트 별로 쓰레드를 만들어야 합니다.
- 쓰레드가 많이질수록 CPU의 컨텍스트 스위칭 횟수가 증가합니다.
- 쓰레드가 요청한 동작이 수행 가능해질 때 까지 대기합니다.
논블록킹은,
- 호출된 함수가 바로 return 해서 호출한 함수에게 제어권을 주어 다른 일을 할 수 있게 합니다.
- Blocking 방식의 비효율성을 극복하고자 만들게 되었습니다.
- 클라이언트가 I/O 작업을 진행해도 유저 프로세스의 작업을 중단시키지 않습니다.
- 요청된 동작이 현재 수행 불가능하다는 사실을 쓰레드에게 알립니다.
동기방식 (Synchronous)이란,
말 그대로 동시에 일어난다는 뜻입니다. 그리고, 요청과 그 결과가 동시에 일어난다는 약속입니다. 또한, 요청한 자리에서 결과가 주어져야 합니다. 요청을 보낸 후 응답(=결과)를 받아야지만 다음 동작이 이루어지는 방식입니다.동기의 특징은,
- 설계가 매우 간단하고 직관적입니다.
- 어떠한 일을 처리할 동안 다른 프로그램은 정지합니다.
- 실제 cpu가 느려지는 것은 아니지만 시스템의 전체적인 효율이 저하된다고 할 수 있습니다.
- 동기는 요청과 결과가 동시에 이루어지는 것으로, 설계가 간단하지만 결과가 주어질 때까지 아무것도 못하고 대기해야 하므로 비동기식 보다 비효율적입니다.
비동기 방식 (Asynchronous) 이란,
동시에 일어나지 않는다를 의미합니다. 요청과 결과가 동시에 일어나지 않을거라는 약속입니다.비동기의 특징은,
- 동기식 보다 복잡합니다.
- 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로, 자원을 효율적으로 사용할 수 있습니다.
데이터 입출력방식( = 데이터 전송방식)에는,
프로그램에 의한 방식(폴링) < 인터럽트에 의한 방식 < DMA에 의한 방식 < Channel에 의한 방식이 있습니다.
(↑입/출력 처리 능력 순서)
메모리는 원래 CPU만 접근 권한을 가진 작업공간이라 입출력 관리자는 접근이 불가합니다. 직접 메모리 접근 (DMA) 은 인터럽트 방식의 시스템을 구성하는 데 필수 요소이기 때문에, 입출력 관리자는 CPU의 허락 없이도 메모리에 접근할 수 있는 권한, 즉, 직접 메모리 접근 (DMA - Direct Memory Access) 권한을 가져야 합니다.
CPU와 DMA가 동시에 메모리에 접근할 때, CPU의 작업속도보다 입출력장치의 속도가 더 느리기 때문에 DMA에게 사이클(순서)을 양보하게 되는데, 이것을 사이클 훔치기(Cycle Stealing) 라고 합니다.
데드락은 프로세스가 자원을 얻지 못해, 다음 작업을 못하는 상태입니다.
예를 들어보면, 프로세스1과 프로세스2가 각각 자원 A와 B를 얻어야되는데,
프로세스1은 A를, 프로세스2는 B를 가지고 있어서, 서로 무한정 기다리는 상태를 데드락이라고 합니다.
데드락은 다음의 네가지 조건이 동시에 발생해야 성립이 가능합니다.
그 네가지는 상호배제, 점유대기, 비선점, 순환대기(상대방이 자원을 서로 대기하는 것) 입니다.
데드락을 예방하는 방법으로는, 예방 / 회피가 있습니다.
먼저 예방은,
상호배제/점유대기/비선점/순환대기 같이 교착상태 발생조건 4가지 중 하나를 부정함으로써 교착상태를 예방하는 방법입니다.
- 상호 배제 부정
여러 개의 프로세스가 동시에 공유자원을 사용할 수 있습니다.- 점유 대기 부정
프로세스가 실행되기 전에 필요한 모든 자원을 할당하여 프로세스 대기를 없애거나, 자원이 점유되지 않은 상태에서만 자원 요청을 받도록 함- 비선점 부정
모든 자원에 대한 선점을 허용- 순환 대기 부정
자원을 선형으로 분류하여 고유 번호를 할당하고, 각 프로세스는 현재 점유한 자원의 고유번호보다 앞이나 뒤 한쪽 방향으로만 자원을 요구하도록 함
그러나, 이렇게 교착상태 발생조건을 방지해서 데드락을 예방하는 방법은 시스템 처리량이나 자원 사용의 효율성을 떨어트리는 단점이 있습니다.
회피는,
교착상태가 발생할 가능성이 있는 자원을 할당(Unsafe allocation)하지 않고 안전한 상태(Safe state)에서만 자원 요청을 허용하는 방법입니다. 하지만 교착상태 회피를 하기 위해서는 아래와 같은 가정이 필요합니다.
- 프로세스 수 고정
- 자원의 종류와 수 고정
- 프로세스가 요구하는 최대 자원의 수를 알아야 함
- 프로세스는 자원 사용 후 반드시 반납
데드락을 회피하기 위한 알고리즘으로 크게 두 가지가 있습니다.
은행원 알고리즘(Banker's Algorithm)과 자원 할당 그래프 알고리즘(Resource-Allocation Graph Algorithm) 입니다.
은행원 알고리즘은, 자원 할당 결정전에 예상되는 모든 자원의 최대 할당량을 가지고 시뮬레이션을 하여 safe state에 들 수 있는지 여부를 검사하여 교착상태의 가능성을 미리 조사하는 알고리즘입니다.
기본 개념 자체는 "CPU는 최소한 하나의 프로세스에게 할당해줄 만큼의 자원을 항상 보유하고 있어야 한다" 입니다.자원 할당 그래프는, 예약 간선을 추가하여 예약 간선으로 설정한 자원에 대해서만 자원 할당을 요청할 수 있고 사이클이 형성되지 않을 때만 자원을 할당받는 방법입니다.
Safe state : safe sequence(교착상태를 발생시키지 않고 자원을 할당하는 순서)가 존재하며 모든 프로세스가 정상적으로 종료될 수 있는 상태를 의미
Unsafe state : 교착상태가 발생할 가능성이 있는 상태
회복 기법은 교착상태가 발생했을 때 해결하는 기법을 의미합니다.
기법 종류로는 사용자 처리와 시스템 처리가 있습니다.
사용자 처리는, 교착상태에 있는 프로세스 중 하나의 프로세스를 사용자가 강제 종료시키는 것 입니다.
시스템 처리는 두가지로 나뉘는데,
첫번째는, 프로세스 중지입니다.
교착상태에 속해있는 모든 프로세스를 중지하거나 교착상태가 해결될 때까지 한 프로세스씩 중지
두번째는, 자원선점 입니다.
프로세스들로부터 자원을 빼앗아 교착상태가 해결될 때까지 다른 프로세스들에게 자원을 할당합니다.
PCB란 Process Control Block의 약자로, 프로세스 제어 블록 입니다.
PID, 상태, 다음 명령어 주소 등 프로세스에 대한 중요한 정보를 저장합니다.
프로세스 생성시 만들어지며, CPU의 주기억장치에서 유지됩니다.
다른 프로세스를 처리할 때 PCB에 상태를 저장하고 나중에 그 작업을 다시 불러와 작업 재개가 가능해집니다.
공유된 자원에서 여러 프로세스 및 스레드가 동시에 접근할 경우 경쟁 상태(race condition) 같은 문제가 발생하는데, 이를 막기위한 규칙을 프로세스(스레드) 동기화라고 합니다. 대표적인 동기화 종류로는, Mutex(뮤텍스), Semaphore(세마포어), Monitor(모니터) 가 있습니다
임계구역이란, 여러 개의 프로세스가 공유하는 데이터 및 자원에 대해서 어느 한 시점에서는 하나의 프로세스만 자원 또는 데이터를 사용하도록 제한하는 코드 영역을 의미합니다. 임계구역은 특정 프로세스가 독점할 수 없습니다.
뮤텍스는, 상호배제라고도 하며, 임계 영역을 가진 쓰레드의 러닝타임이 서로 겹치지 않게 각각 단독으로 실행하는 기술입니다. 즉, 임계구역에 하나의 스레드만 접근이 가능합니다.
세마포어는, 스레드 접근성을 높이고자 사용되며, 임계구역에 여러 스레드가 접근이 가능합니다. 카운터를 두어서 동시에 자원에 접근할 수 있도록 스레드 수를 제어하여 다중 프로세스에서 행동을 조정하거나 동기화 시키는 기술입니다.
스레드를 단일 또는 여러개 제어할 수 있는 세마포어는 뮤텍스가 될 수 있지만, 단일 스레드만 처리하는 뮤텍스는 세마포어가 될 수 없습니다. 그리고, 세마포어는 시스템 범위에 걸쳐있고 파일 시스템 상의 파일 형태로 존재합니다. 반면, 뮤텍스는 프로세스 범위를 가지고 프로그램이 종료될 때 자동으로 지워집니다.
정리하자면, 뮤텍스는 동기화 대상이 하나일때, 세마포어는 하나 이상일 때 사용합니다.
하나의 프로세스 내의 다른 스레드 간 동기화에 사용되는 기술입니다. 뮤텍스의 상위호환 개념으로, 사용자가 프로세스에 lock을 거는 등 동기화 제약 조건을 명시적으로 코딩할 필요가 없다는게 특징입니다.
(뮤텍스는 다른 프로세스간에 동기화할떄 사용)
쓰레드 세이프는 쓰레드에 안전하다는 의미입니다. 좀 더 자세하게 말씀드리자면, 여러 쓰레드가 동작하는 환경에서도 안전하고 결과가 정확하다는(correctness)는 의미입니다.
리앤트런트는 재진입성이라는 의미입니다. 좀 더 자세히 말씀드리면, 여러 쓰레드가 동시에 접근하여 수행하여도 문제가 없다는 의미입니다.
인터럽트와 폴링은 CPU와 입출력 장치 사이의 통신입니다.
인터럽트란,
외부의 인터럽트 핀에 신호가 들어오면 즉시 인터럽트 소스를 실행하고 다시 원래의 코드로 돌아오는 방식입니다. 즉, 하드웨어적으로 시그널을 확인하는 것 입니다.
장점으로는 시그널이 들어온 정확한 타이밍을 알 수 있습니다. 즉, 반응 시간이 빠릅니다. 그리고, 인터럽트 발생시에만 처리를 하기 때문에 시스템 부하가 적습니다.
단점으로는, 폴링보다 구현이 복잡합니다.
그리고, 폴링이란,
특정 주기마다 스레드를 돌면서 시그널이 돌아왔는지 확인하는 방식입니다. 즉, 소프트웨어적으로 시그널을 확인하는 것 입니다.
장점으로는, 구현이 쉽고 우선순위 변경이 용이하다는 것 입니다.
단점으로는, 특정 주기마다 계속 확인해야 하기 때문에, 시스템의 리소스를 많이 소모하고, 정확한 타이밍에 시그널이 들어왔는지 확인하는 것은 불가능하고 주기에 따른 오차가 있습니다.
하나 이상의 구성 요소가 고장나도 시스템이 중단 없이 계속 작동할 수 있는 성능을 의미합니다.
- 복제
동일한 시스템 또는 하위 시스템의 여러 동일한 인스턴스를 제공 하며, 모든 인스턴스에 병렬로 직접 작업 또는 요청을 제공하고 중재에 따라 올바른 결과를 선택합니다.- 실패를 모르는 컴퓨팅
다른 컨텍스트에서 적용할 수 있는 오류에도 불구하고 컴퓨터 프로그램이 계속 실행될 수 있습니다.- 복구 양치기
소프트웨어 프로그램이 치명적인 오류로부터 복구 할 수있는 경량 기술입니다.- 회로 차단기
이 설계 패턴은 분산 시스템의 치명적인 오류를 방지하는 기술입니다.