- 하드웨어 자원 관리 소프트웨어
- 하드웨어와 프로그램의 상호작용을 관리
- 운영체제의 핵심 기능 담당
- 운영체제도 프로그램으로 메모리에 적재 되어야하지만 너무 큼, 때문에 핵심 적인 부분을 메모리에 적재
- 이 적재 시킨 운영체제의 핵심 부분이 커널
Code, Data, Heap, Stack 이 있다.
- Code : 프로그램의 코드 영역, text 영역
- Data : 전역변수, 정적 변수, 상수가 저장
- 초기화된 데이터, BSS, ROM에 저장, 사라지면 안되기 때문
- 초기화 되지 않은 데이터, GVAR, RAM에 저장, 사라져도 괜찮
- Stack : 메서드 호출, 지역 변수, 매개변수 영역
- 크기는 컴파일 시 지정
- 함수의 호출과 함께 할당, 함수 호출 종료시 소멸
- 메모리 높은 주소에서 낮은 주소로 할당
- 때문에 가장 나중에 들어온 것이 먼저 인출
- Heap : 동적할당 (new) 영역, 사용자가 직접 관리
- FIFO 방식
- 일반적으로 낮은 주소에서 높은 주소로 할당(항상 그런것은 아님 -> 단편화 발생가능성때문)
- 때문에 먼저들어온 데이터가 먼저 처리
- 런타임시 크기 결정
- 스택은 LIFO구조로, 메모리에 데이터를 자동으로 할당 및 해체 (추가적인 연산 필요 X)
- 힙은 동적 메모리 할당 및 해제의 복잡한 메모리 관리를 처리해야함
- 스택 포인터 레지스터
- CPU에 스택 포인터 레지스터가 존재, 이를 통해 스택의 Top을 가리키며 빠르게 데이터 추가 및 제거 가능
- 캐시 친화적 : 스택은 메모리 상에서 연속적인 블록을 차지하기에 CPU의 캐시 메모리와 친화적
- 힙은 분산되어 저장됨
스택
- 메서드, 지역변수, 매개변수
- 컴파일 시간에 크기 지정
- FILO 구조
- 크기 제한
- 빠름
- 높은 주소 -> 낮은 주소
- 알아서 소멸되기에 따로 관리 필요 없음
힙
- 동적 할당 부분(new)
- 런타임 시간에 크기 지정
- FIFO 구조
- 크기 제한 없음
- 느림
- (일반적으로)낮은 주소 -> 높은 주소
- 힙 영역 관리 필요
- 힙 영역은 동적으로 생성된 데이터들이 적재
- 힙 영역의 데이터 관리를 위해 Garbage Collect 수행
- 영역이 커지면 Garbage Collector가 참조 여부를 확인해야하는 범위가 커짐
- 프로세스 : 프로그램을 사용하기 위해 메모리에 올린 상태
- 프로세스들은 영역을 공유하지 않음
- 다른 프로세스에 접근하려면 프로세스 간의 통신(IPC)를 사용해야 한다(Ex. 파이프, 파일, 소켓 등을 이용)
- 오류가 생겨도 다른 프로세스에 영향 안줌
- 동기화 필요없음
- 무거움
- PCB, code, data, heap, stack 영역을 갖고있음
- 쓰레드 : 프로세스를 처리하기 위한 최소한의 일의 단위
- 쓰레드는 code, data, heap 영역을 공유, stack을 별도로 소유
- 공유되는 영역에 대한 동기화 필요
- 오류 생기면 다른 쓰레드에게 영향줌
- 가벼움
Context-Switching
- 현재 CPU를 사용하고 있는 프로세스를 중단하고 다른 프로세스를 실행시키는 것
- CPU에서 실행할 프로세스를 교체하는 기술
왜 필요한가
- CPU의 효율을 올리기 위해
- 프로세스가 순서대로 처리된다면 프로세스의 I/O 작업 동안에는 CPU가 쉬게됨
- 이 쉬는 시간동안에도 CPU가 일하게 하도록 하기위해서 컨텍스트 스위칭으로 다른 프로세스를 적재
- 프로세스를 관리하기위한 정보를 포함하는 커널의 자료구조
- 운영체제가 프로세스 생성할때 PCB 생성
- PCB 정보는 중요하기에 사용자가 접근할 수 없는 메모리 영역(OS 메모리 영역)에 저장
- PID, 프로세스 상태 등 저장
- PCB는 프로그램 카운터와 레지스터 정보(스택 포인터 등)를 저장하고 CPU는 문맥 전환시 이 정보를 사용
- 쓰레드라면 오류가 발생했을때 다른 창에 영향 줌
- 하지만 그렇지 않기 때문에 별개의 프로세스로 진행되는 것을 알 수 있음
- 그렇지만! 각각의 크롬창은 영향을 주지않지만 하나의 창에서는 영향을 줄 수 있고 여러가지 작업을 동시에 실행가능
즉, 크롬은 멀티쓰레드이자 멀티프로세싱인 하이브리드 방식이다.
멀티 쓰레드
- 하나의 프로세스를 여러개의 쓰레드로 작업
- 적은 메모리공간 사용
- Context Switching이 빠름
- CPU는 프로세스에게 할당되지만 내부에서 각각의 스레드에게 할당되기에 컨텍스트 스위칭 필요- 오류나면 전체 쓰레드가 영향
- Ex. 웹 서버
멀티 프로세스
- 하나의 프로그램을 여러개의 프로세스로 작업
- 많은 메모리 공간 사용
- Context Switching이 쓰레드에 비해 느림
- 오류나면 다른 프로세스 영향 끼치지 않음
- Stack 영역
- Stack 영역은 메서드 호출이 가능
- 즉, 스레드마다 프로세스 내에서 독립적인 실행이 가능하도록
- PC(Program Counter) Register
- 쓰레드가 명령어를 어디까지 수행했는지 나타냄
- TCB(Thread Control Block) 안에 존재
- 다음 CPU를 할당 받을때 이어서 실행하기위함
- 쓰레드는 자원을 공유하기때문에 동기화문제를 고려해야함
- 다른 쓰레드가현재 쓰레드가 사용하는 자원을 변경하는 것이 문제
- 동기 : 여러 작업들이 순서대로 작동되는 것을 의미
- 즉, 하나의 작업이 종료될때까지 기다림
- 대기해야함
- 비동기 : 작업들의 순서를 기다리지 않고 바로 실행
- 하나의 작업이 종료될때까지 기다리지 않음
- 다른 작업을 효율적으로 사용 가능
- 요청한 작업이 끝나면 CallBack으로 끝났음을 알림
- blocking : 호출되면 내 함수가 끝날때까지 주도권을 넘기지 않음
- non-blocking : 호출되면 주도권을 넘김
- 자식 프로세스 : fork로 자식 프로세스를 생성, 부모 프로세스의 데이터 복사
- 웹 서버에서 각 클라이언트의 요청을 처리하기 위해 요청마다 새로운 자식 프로세스 생성
- 프로세스를 생성해서 병렬적으로 작업을 빠르게 처리하도록
- 데몬 프로세스 : 백그라운드에서 동작하며 서비스를 제공하는 프로세스
- 백그라운드 : 사용자가 보지못하는 뒷편
- 자동으로 작동
- 고아 프로세스 : 부모 프로세스가 먼저 종료되어 고립된 프로세스
- 좀비 프로세스 : 자식 프로세스가 종료되었는데 작업 종료에 대한 승인을 받지 못한 상태
- Race Condition : 두개 이상의 쓰레드 또는 프로세스가 하나의 자원에 접근하기위해 경쟁하는 것
- Critical Section : Race Condition이 발생할 수 있는 영역
해결방법
- Mutext와 SemaPhore를 사용해서 Critical Section에 하나의 프로세스만 접근 가능하도록 합니다.
- DeadLock : 각자가 서로 자원들 갖고있는 상태에서 서로의 자원을 얻기 위해 무한히 기다리는 상태
- 상호배제 : 하나의 자원에 여러 프로세스가 접근할 수 없음
- 점유대기 : 하나의 자원을 소유한 상태로 다른 자원을 기다림
- 비선점 : 이미 선점된 자원을 뺏을 수 없음
- 순환대기 : 프로세스들이 순환적으로 다음 프로세스가 요구하는 자원을 소유
- 예방 : DeadLock 발생조건 중 하나 제거
- 회피 : 자원을 할당하기 전에 데드락이 발생하는지를 사전에 확인하고 피함
- 회복 : 현재 데드락이 발생했는지를 확인하고 회복
데드락을 해결할 수 있는 회피방법에 사용되는 알고리즘
- 은행원은 사람들에게 대출을 해준다
- 모든 사람들이 원하는 대출금액을 해줄 수 없어서 각각의 사람들에게 특정한 금액만큼 먼저 빌려줌
여기서부터 상황이 나뉨
- 안전한 상태
- 특정한 금액만큼 빌려주고 남은 금액으로 한 사람이 원하는 대출금을 제공할 수 있어서 대출해주고 갚을때까지 기다리고 다음 사람 해결하는 식
- 교착 상태
- 특정한 금액만큼 빌려주고 난 뒤에 남은 금액으로 어떠한 사람의 대출금을 제공할 수도 없게됨
- 철학자들은 원탁 식탁에 앉아서 식사
- 철학자들마다 앞에 음식이 있고 양옆에 포크가 위치한다.
- 식사를 하기위해 모든 철학자는 왼쪽의 포크를 손에쥠
- 철학자들은 모두 오른쪽 포크를 기다리면서 무한정 대기 : DeadLock 발생
- 방에 들어올 수 있는 인원을 설정
- 5개의 포크가 존재한다면 식사를 할 수 있는 최대인원 4명만 입장 가능 하도록
- 이 방법을 세마포어라고 한다.
- 뮤텍스 : 하나의 자원을 이미 프로세스가 사용하고 있다면 다른 프로세스는 접근하지 못한다.(오직 1개)
- 세마포어 : 세마포어 변수 만큼 프로세스가 접근 가능
- 세마포어 변수는 여분의 자원을 표시
- 2는 2개의 프로세스가 더 접근 가능
- -2는 2개의 프로세스가 이미 대기하고 있음
비슷한 개념이지만, 동일한 것은 아니다.
공통점
- 둘다 동기화 도구로 사용된다.
- 단일 리소스의 접근을 제어한다.
차이점- 이진 세마포어
- 0 또는 1이라는 세마포어 변수 값을 이용해 제어
- 소유권이 존재하지않음, 즉, 현재 자원을 소유하고있지 않은 쓰레드가 세마포어 변수를 제어해서 자원을 소유할 수 있음 -> 이는 불안전한 상황
- 때문에, 세마포어의 변수를 적절히 조절할 수 있도록 설계가 중요
- 뮤텍스
- 잠금 또는 해제의 상태로 쓰레드의 접근을 제어
- 소유권이 존재, 잠근 쓰레드만 해제가 가능
- CPU가 쉬지않고 최대한 일할 수 있도록 하기위해서 대기하는 프로세스에게 CPU를 할당하는 알고리즘
비선점
- FCFS(First Come Fisrt Start) : 들어온 순서대로
- SJF(Shortest Job First) : 처리시간이 가장 짧은 프로세스
- HRN(High Response Ratio Next) : 대기 시간에 따른 비율이 가장 높은 프로세스
- 처리시간/대기시간
선점
- RR(Round Robin) : 대기하고있는 프로세스들에게 일정한 시간만큼 부여
- 시간이 지나면 다음 프로세스가 선점
- SRTF(Sortest Remaining Time First) : 처리시간이 가장 짧은 프로세스
- 짧은 프로세스가 대기큐에 처리시간이 더 짧은 프로세스가 있다면 뺏김(SJF와 비슷)
- MFQ(Multilevel Feedback Queue) : 각 단계마다 하나의 큐를 두고, 단계 마다 정해진 시간내에 처리하지 못하면 다음 낮은 큐로 보내짐
- 우선순위가 낮을 수록 더 많은 시간을 배정, 해당 작업을 집중적으로 해결하기 위함
- MLQ의 기아 문제를 해결하기 위함
에이징 기법 : 기다린 시간에 비례해서 우선순위를 한 단계씩 높여주는 방법, 기아 상태 예방
- 이용률 : CPU가 쉬지않고 일한 시간
- 처리량 : 단위 시간당 처리량
- 소요시간 : 프로세스를 처리하는데 사용한 CPU사용시간 + 기다린 시간
- 대기시간 : 프로세스가 Ready Queue에서 기다린 시간
- 응답시간 : 프로세스가 들어가서 CPU를 할받는데 까지 걸린 시간
- 선점 : 프로세스가 CPU를 사용하고 있어도 CPU의 할당을 뺏어서 다른 프로세스에게 할당
- System Call, Time Quantum, Interrupt 등에 의해서 선점이 발생
- Time Quantum : RR 스케줄링으로 부여받은 시간
- 비선점 : 프로세스가 CPU를 사용하고 있다면 뺏지 못함
- 커널에서 제공하는 핵심적인 기능을 사용하기 위한 방법(인터페이스)
- 운영체제는 커널의 기능을 사용하기위해서는 System Call을 사용해야만 가능하도록 제한
- 때문에 컴퓨터 자원을 보호하며 서비스 제공 가능
Interrupt : 프로그램이 실행되고 있는 중에 입출력과 같은 특정한 상황이 발생하면 CPU는 실행하던 프로그램을 멈추고 이 상황을 처리하는 것
- CPU에 접근하는 속도의 차이를 나누기 위함
- 프로세스는 각자 독립적인 메모리 공간을 소유
- 즉, 프로세스는 다른 프로세스에 접근 불가
- OS는 커널영역과 사용자 영역에 접근 제한이 없음
- 때문에 오로지 OS 만이 메모리관리 가능
- 운영체제의 핵심적인 역할을 수행하는 커널의 영역이 커널영역
- 커널영역에 사용자가 마음대로 접근한다면 시스템이 불안정
가변 길이 할당 방식에서 사용되는 방식으로, 메모리 FIT은 프로세스에 적합한 메모리 블록을 선택하는 방법
- First Fit : 처음부터 시작해서 가장 첫번째로 접근되는 곳에 적합
- Next Fit : 가장 마지막으로 접근했던 곳에서부터 시작해서 첫번째로 접근되는 곳에 적합
- Best Fit : 가장 크기가 알맞는 공간에 적합
- Worst Fit : 가장 크기의 차이가 큰 공간에 적합
페이징
- 프로세스를 동일한 크기의 페이지로 분리(페이지)
- 메모리를 페이지와 동일한 크기로 분리(프레임)
- 메모리에 불연속적으로 데이터를 저장하는 방식
- 내부단편화 발생 가능
세그멘테이션- 프로세스를 가변적인 크기로 분리(세그먼트)
- 세그먼트를 그대로 메모리에 불연속적으로 적재
- 외부단편화 발생 가능
- 단편화 : 프로세스들이 차지하는 메모리 공간들 사이에서 낭비되는 작은 공간
내부단편화- 메모리를 일정한 크기로 분할해서 사용할때 발생
- 일정한 크기로 분할한 곳에 해당 크기보다 작은 데이터를 적재
- 일정한 크기에 적재되었지만 남는 공간 : 내부단편화
외부 단편화
- 메모리에 데이터를 가변적으로 적재
- 데이터를 적재하는 과정을 반복하다 보니 사이사이 공간들이 발생
- 이 공간들을 합쳐보니 적재되어야할 데이터가 적재될 수 있는 공간인데도 적재되지 못함 : 외부단편화
- 메모리에 프로세스 전체가 적재되지 않아도 실행이 될 수 있게 하는 기법
- 크기가 커서 메모리에 적재될 수 없는 프로그램을 메모리에 올라와있다고 착각하게 하도록 가상 주소에 적재
- 적재된 프로세스의 부분이 필요한 상황에 실제 메모리와 Swap
- 즉, 프로세스의 필요한 부분만 메모리에 적재해서 실행
- 프로그램을 실행시킬때 프로그램 전체를 메모리에 올리는 것이 아닌 필요한 부분만 메모리에 적재하는 전략
- 가상메모리에 사용
- 페이징을 사용
- 메모리를 페이징 단위로 분리해서 사용(프레임)
- 분리한 부분에 페이지를 적재시켜서 프로세스의 부분을 실행
- 공간이 부족해 메모리에 적재시키지 못한 페이지는 하드디스크의 스왑영역에 저장
- 스왑영역에 저장된 페이지가 사용되어야할때 메모리에 적재된 페이지와 교체해야하는 상황
- FIFO(First In First Out) : 가장 처음에 적재되었던 페이지와 교체
- LRU(Least Recently Used) : 가장 오랫동안 사용되지 않은 페이지와 교체
- LFU(Least Frequently Used) : 가장 적게 사용되었던 페이지와 교체
- OPT(Optimal, 최적) : 가장 나중에 실행될 페이지와 교체(최적이지만 사실상 불가능)
- MFU(Most Frequently Used) : 가장 많이 사용되는 페이지와 교체
- NUR(Not Used Recently) : LRU와 비슷, 가장 오랫동안 사용되지 않은 페이지와 교체
- 참조비트, 변형비트 사용
- 참조되면 1 아니면 0
- 변형되면 1 아니면 0
- 00인것과 교체
쓰레싱
- 페이지 부재율이 높은 상태
- 페이지 부재율이 높다면 페이지를 교체하는데 많은 시간이 사용
- CPU가 일을 안하고 놀게되기 때문에 일처리가 늦어지고 더 많은 프로세스가 대기
- 이러한 악순환이 쓰레싱
실행되는 프로세스가 많아지면 프로세스에게 할당되는 프레임의 개수도 줄어듬쓰레싱을 해결하기 위한 방법?
- Working Set
- 대부분의 프로세스가 특정 페이지만 사용하는 것을 이용
- 일정 시간동안 참조되는 페이지의 개수를 파악
- 예를들어, 일정시간동안 0, 1, 0, 2, 3, 2 페이지가 사용되었다면 Working set은 {0, 1, 2, 3}이 된다
- 그 개수만큼 프레임이 확보되면 그 때 메모리에 적재
- Page Fault Frequency
- Page Fault의 하한과 상한을 설정
- 상한을 넘으면 프레임 개수를 추가
- 하한을 넘으면 프레임 개수를 줄임
- 메모리에서 자주 사용되는 데이터를 따로 저장해서 사용하는 구조
- CPU와 메모리의 속도차이를 완화하기 위해 사용하는 메모리 종류
- CPU는 매우 빠른 속도로 데이터를 처리
- 메모리는 상대적으로 느린 속도를 갖음
- 메모리의 속도를 CPU가 기다려줘야하는 상황이 발생
- 이러한 상황때문에 전체 시스템이 영향을 받는 병목현상 발생
병목현상 : 하나의 구성요소로 전체 시스템이 영향을 받는 현상
- 데이터의 이동에는 CPU가 필요
- 다량의 데이터 이동에는 CPU가 많은 부담을 느낌
- 때문에 CPU를 거치지 않는 DMA 방법 사용
DMA 컨트롤러라는 하드웨어 장치가 관리, CPU가 초기설정해주고 이후 작업은 DMA 컨트롤러가 진행
연속방식
- 프로세스 전체를 분할된 메모리 형태(파티션)에 적재
- 프로세스의 정보가 연속적으로 저장
- 고정분할, 가변분할
- 고정 분할 : 메모리를 고정된 크기로 분할
- 프로세스마다 동일한 크기가 아니고, 프로세스마다 정해진 파티션의 크기의 메모리 공간
- 프로세스보다 크거나 같은 파티션에 할당
- 가변 분할 : 메모리를 동적인 크기로 분할
- 분할된 파티션의 크기가 계속해서 변함
불연연속 방식
- 프로세스를 분리해서 메모리에 적재
- 프로세스의 정보가 불연속적으로 저장
- 페이징, 세그멘테이션
- 연속할당 방식은 프로세스를 분할하지 않고 분할된 하나의 파티션에 하나의 프로세스를 적재
- 페이징 기법은 나누어진 메모리(프레임)에 프로세스도 같은 크기의 페이지 단위로 나눠서 적재
이는 가변분할과 세그멘테이션 에서도 동일
- FCFS, SJF, HRN, RR, MFQ
- FIFO, LRU, LFU