1. 운영체제란?
하드웨어 위에 설치되어 하드웨어와 소프트웨어 계층을 연결하는 소프트웨어 계층이다.
컴퓨터 시스템의 자원을 관리하고, 사용자가 컴퓨터를 사용할 수 있는 환경을 제공한다.
윈도우, 맥OS, 리눅스. 유닉스 등이 있다.
2. 운영체제의 목적
- 처리능력 향상 : 일정 시간 동안 시스템이 처리하는 일의 양
- 반환 시간 단축 : 요청한 작업을 완료할 때까지 소요되는 시간
- 사용 가능도 향상 : 시스템 자원을 얼마나 빨리 제공할 수 있는가
- 신뢰도 향상 : 주어진 문제를 정확하게 푸는지
→ 이처럼 한정된 컴퓨터 자원을 관리하는 시스템이므로 성능을 평가하는데 위 4가지 기준이 사용된다.
3. 운영체제의 구조
- GUI : 사용자가 상호 작용할 수 있도록 하는 사용자 인터페이스의 한 형태
- 시스템콜 : 운영체제가 커널에 접근하기 위한 인터페이스, 유저 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출할때 쓴다.
- 커널 : 운영체제의 핵심 부분이자 시스템콜 인터페이스를 제공하며, 보안, 메모리, 프로세스, 파일 시스템, IO 관리 등 운영체제의 중추 역할을 한다.
- 드라이버 : 하드웨어를 제어하기 위한 소프트웨어
4. CPU와 메모리 구조
CPU는 프로그램을 실행하는 데 필요한 연산을 처리하고 수행한다. 프로세서 라고도 한다.
메모리는 데이터를 저장하기 위한 기억 장치로, 휘발성 메모리인 주 기억장치(RAM)와 비휘발성 메모리인 보조 기억장치(SSD, HDD)가 있다. 주기억장치는 메인 메모리를 뜻한다.
- 레지스터 : CPU가 요청을 처리하는 데 필요한 데이터를 임시로 저장하는 기억장치이다. CPU 내부에 존재하며 왕 빠르다.
- 캐시 메모리 : CPU와 RAM 사이의 속도 차이를 해결하기 위한 장치이다. CPU 내부에 존재한다.
- RAM(Random Access Memory) : 프로그램을 실행할 때 필요한 정보를 저장한다.
- 하드 디스크 : 사용자가 필요한 데이터와 프로그램을 저장한다.
그러므로,
- 프로그램을 실행하면 운영체제가 디스크에 있는 프로그램을 RAM으로 load한다.
- 메모리에 로드한 프로그램을 프로세스라고 하며, CPU가 처리한다.
- CPU는 하나의 프로세스만 처리할 수 있어 OS가 스케줄링을 통해 CPU에 프로세스를 할당한다.
5. 커널과 시스템 콜
커널(kernal)은 OS의 핵심 요소로, 자원 관리를 위해 CPU 스케줄링, 메모리 관리, 입출력 관리 등을 담당한다.
운영체제는 커널에서 관리하는 중요 자원에 사용자가 쉽게 접근하지 못하도록 커널 모드와 사용자 모드를 나눈다.
커널모드에서는 하드웨어에 직접 접근해 자원을 사용할 수 있고, 사용자 모드에서는 커널 자원에 접근할 수 없다.
그러므로, 사용자 모드에서 실행한 프로세스가 자원에 접근하려면 시스템 콜을 호출해 커널에 요청해야 한다.
시스템콜은, 사용자 모드에서 커널 모드에 접근해 필요한 기능을 수행할 수 있게 하는 시스템 함수다.
프로세스 제어, 장치 제어, 파일 조작등을 수행하며, 대표적인 예로는 fork(), wait()같은 함수 등이 있다.
6. 프로세스
프로세스는 기술 면접에 아주 자주 나온다...
프로세스(process)는 컴퓨터에서 실행 중인 하나의 프로그램을 의미한다.
프로그램은 특정 작업을 수행하기 위한 명령어의 집합이다. 운영체제는 프로그램을 실행하면서 디스크에 저장된 데이터를 메모리로 로드한다. 프로세스는 독립된 메모리 영역(스택, 힙, 데이터, 코드)을 할당받으며, 다른 프로세스의 메모리 영역에 접근할 수 없다.
프로세스에 할당된 독립된 메모리 영역 구조는 다음과 같다.
- 스택 : 지역 변수, 함수의 매개변수(파라미터), 리턴 주소 값 등을 저장한다. 컴파일 할 때 영역 크기가 지정된다.
- 힙 : 동적 메모리 영역, 즉 사용자 동적 할당 공간이다. malloc()과 같은 함수를 사용할 때 할당되는 영역이다. 런타임 때 영역 크기 결정된다.
- 데이터 : 전역 변수, 정적 변수(static), 배열 등을 저장한다.
- 코드 : 실행할 코드(기계어)가 기계어로 컴파일 되어 저장되는 영역이다.
- 스택 영역이 힙 영역을 침범하면 스택 오버플로, 힙 영역이 스택 영역을 침범하면 힙 오버플로이다.
OS는 프로세스를 제어하기 위해 프로세스 정보를 저장하는데, 이를 PCB(Process Control Block) 이라고 한다.
PCB는 현재 프로세스의 상태, PID, 다음 실행할 명령어의 주소인 PC(program counter), 프로세스의 우선순위 등을 저장한다.
또한, 프로세스의 상태는 다음과 같은 5가지의 상태가 있다.
- 생성(new): 프로세스가 PCB를 가지고 있지만 OS로부터 승인받기 전
- 준비(ready): OS로부터 승인받은 후 준비 큐에서 CPU 할당을 기다림
- 실행(running): 프로세스가 CPU를 할당받아 명령어를 실행함
- 대기(waiting): 프로세스가 입출력이나 이벤트 발생을 기다려야 해서 CPU 사용을 멈추고 기다림
- 종료(terminated): 프로세스 실행 종료
7. 스레드
프로세스는 한 개 이상의 스레드를 갖는데, 스레드(thread)는 프로세스에서 실제로 실행되는 흐름의 단위를 의미한다. 스레드는 프로세스 안에 존재하므로 프로세스의 메모리 공간을 이용하고, 스택 영역을 할당받는다. 스택을 제외한 영역(힙, 데이터, 코드)은 다른 스레드와 공유한다.
8. 멀티 프로세스와 멀티 스레드
- 동시성(concurrency) : 하나의 코어(싱글 코어)에서 여러 작업을 번갈아 가면서 처리하는 방식이다. CPU는 한 번에 하나의 작업만 처리할 수 있어서 여러 작업을 조금씩 돌아가면서 처리한다. 이렇게 하나의 CPU에서 여러 작업을 번갈아 가면서 처리하며 작업을 교체하는 것을 콘텍스트 스위칭(context switching) 이라고 한다.
- 병렬성(parallelism) : 여러개 코어(멀티 코어)가 있어서 각 CPU에서 각 작업을 동시에 처리하는 방식이다.
멀티 프로세스
응용 프로그램 하나를 여러 프로세스로 구성하는 것을 의미한다. 멀티 프로세스에서 한 프로세스가 죽어도 다른 프로세스에 영향을 주지 않으므로, 응용 프로그램을 프로세스 하나로 구성하는 것보다 여러 개로 구성하는 것이 안정적이다.
하지만, 시간과 메모리 공간을 많이 사용한다는 단점이 있다. CPU는 하나의 작업만 처리할 수 있는데, 여러 프로세스를 처리하려면 콘텍스트 스위칭 작업이 이루어져야한다. 이때 교체되는 시간과 메모리를 오버헤드(overhead)라고 한다.
또한, 프로세스 간 공유할 자원이 있다면 IPC(Inter Process Communication)를 통해 프로세스 간 자원을 공유해야 한다. 그래서 직접 메모리를 참조하는 것보다 비효율적이다.
멀티 스레드
멀티 스레드(multi thread)는 한 프로세스 내에서 스레드를 여러 개 생성해 스레드들이 각자 다른 작업을 처리하는 것을 의미한다.
스레드간에 힙, 데이터, 코드영역을 공유하므로 콘텍스트 스위칭 시 오버헤드가 적게 발생하고 IPC를 사용하지 않아 멀티 프로세스의 단점을 보완할 수 있다.
→ 독립적인 메모리 공간을 갖는 멀티 프로세스보다, 스레드를 여러 개 생성하는 것이 자원을 효율적으로 사용할 수 있다.
하지만 공유 자원에 대한 동기화가 필수적이다.
9. 프로세스 동기화
여러 프로세스 또는 여러 스레드에서 하나의 공유 자원에 접근하는 경우가 있는데, 이때 자원에 접근하는 순서에 따라 결과 값이 달라질 수 있다. 이를 경쟁 상태(race condition)이라고 한다.
임계영역
공유 자원에 접근할 수 있고 접근 순서에 따라 결과가 달라지는 코드 영역을 임계 영역(critical section) 이라고 한다.
이미 실행한 코드를 실행된 줄 모르고 한 번 더 실행시키면 원하지 않는 결과가 나오기 때문이다.
임계 영역에서 경쟁 상태가 발생하는 것을 방지하려면 여러 프로세스가 공유 자원에 접근해도 데이터의 일관성이 유지되도록 프로세스 동기화(process synchronization)을 해야 한다.
상호배제 기법(mutax exclusive)
어떤 프로세스가 임계 영역을 실행 중일 때 다른 프로세스가 임계 영역에 접근할 수 없는 기법이다.
뮤텍스와 세마포어가 있다.
뮤텍스(mutex)
뮤텍스는 락(lock)을 가진 프로세스만이 공유 자원에 접근할 수 있게 하는 방법이다.
임계 영역에 먼저 접근한 프로세스가 있어 임계 영역에 락을 걸면 다른 프로세스들은 해당 프로세스가 락을 해제해야 하기 전까지 대기해야 한다.
이처럼 임계 영역에 접근한 프로세스가 임계 영역에 락을 거는 것이다.
임계 영역에 접근하지 못한 프로세스는 락을 얻기 위해 락이 풀릴 때 까지 반복문을 돌며 확인한다. 이를 바쁜 대기(busy waiting)라고 부른다.
세마포어(semaphore)
공유자원에 접근할 수 있는 프로세스의 수를 정해 접근을 제어하는 방법이다.
임계영역에 접근할 수 있는 키 n개를 지정하고 이중 하나를 가진 프로세스 만이 임계 영역에 접근 하게 하는 방식이다.
뮤텍스는 한 번에 한 스레드만 접근할 수 있지만, 세마포어는 여러자원에 대한 병렬 접근이 유용하다.
10. 스케줄링
멀티 프로세스 환경에서는 여러 프로세스가 모두 실행되어야 하지만, CPU 자원은 한정적이므로, 스케줄링을 통해 모든 프로세스를 공평하게 실행해 한정된 자원을 효율적으로 활용하는 것이다.
이에대한 알고리즘은 비선점형과 선점형으로 나뉜다.
비선점형 스케줄링(non-preemptive scheduling)
실행 중인 프로세스가 종료될 때까지 다른 프로세스를 실행할 수 없음을 의미한다.
FCFS(First Come First Served), SJF(Shortest Job First), HRRN(Highest Response Ratio Next) 스케줄링이 있다.
- FCFS 스케줄링 : 준비 큐에 먼저 들어온 프로세스를 먼저 실행시킨다.
- SJF 스케줄링 : 실행 시간이 짧은 프로세스가 우선순위를 갖는 알고리즘이다.
- HRRN 스케줄링 : 응답률 = (대기시간 + CPU요구량) / CPU요구량인 응답률을 우선으로 하는 알고리즘이다.
선점형 스케줄링(preemptive scheduling)
선점형 스케줄링(preemptive scheduling)은 스케줄러가 실행 중인 프로세스를 중단시키고 다른 프로세스를 실행할 수 있음을 의미한다. RR(Round Robin) 스케줄링, SRTF(Shortest Remaining Time First)스케줄링, 멀티 레벨(multi level) 스케줄링이 있다.
- RR 스케줄링: 비선점형 스케줄링과 달리 프로세스 간 우선순위가 없다. 모든 프로세스를 순서대로 일정 시간 동안 실행한다.
- SRTF 스케줄링: 준비 큐에서 대기 시간이 가장 짧게 남은 프로세스를 우선 수행하는 알고리즘이다.
- 멀티 레벨 스케줄링: 준비 큐를 목적에 따라 여러 개로 분리해 사용하는 알고리즘이다.
11. 메모리 관리 전략
다수의 프로세스를 실행하려면 한정된 메모리 공간내 많은 프로세스를 로드해야 하므로 연속 메모리 할당, 페이징, 세그먼테이션등과 같은 메모리 관리 전략이 있다.
연속 메모리 할당(contiguous allocation)
멀티프로세스 환경에서 여러 프로세스를 메모리에 연속적으로 로드하는 방법이다. 고정 분할 방식(메모리 영역을 분할한 뒤, 각 영역에 프로세스를 할당하는 방식)과 가변 분할 방식(할당한 프로세스의 크기에 따라 메모리 공간을 분할하는 방식)으로 나누어진다.
비연속 메모리 할당
프로세스의 메모리 영역을 나눠서 메모리 공간에 저장하는 방법으로, 페이징과 세그먼테이션으로 나눠진다.
- 페이징(paging) : 프로세스의 논리 메모리 영역과 물리 메모리 영역을 각각 일정한 크기의 페이지와 프레임으로 나눈다. 각각 번호를 할당해 메모리에 할당하며 페이지를 물리 메모리에 연속으로 할당할 필요가 없어진다.
- 세그먼테이션(segmentation) : 프로세스의 메모리 영역을 논리적 단위인 세그먼트로 분할해 메모리를 할당한다.
가상메모리
디스크에 저장된 데이터를 메모리(RAM)에 로드할때, 메모리 공간의 한계를 극복하기 위해 등장한 개념이다.
프로세스의 일부만 메모리에 로드하고, 나머지는 디스크에 둔 상태로 프로세스를 실행하는 방식이다. 프로세스 전체가 메모리에 로드되지 않아도 실행에는 문제가 없기 떄문이다.
스레싱(thrashing)
동시에 일정 수 이상의 프로그램을 실행했을 때 오히려 CPU 이용률이 떨어지는 상황을 말한다.
가상 메모리를 구현해 멀티 프로그래밍을 하면 CPU 이용률이 높아지는데, 일정 수 이상으로 다중 프로그래밍을 하면 페이지 폴트(프로그램을 실행하다가 물리 메모리에 필요한 페이지가 없음, 가상 메모리에서 안올라 왔기 때문)가 자주 일어난다. 따라서 오히려 CPU 이용률이 떨어지는 현상을 스레싱이라고 말한다.
이를 예방하기 위해 워킹세트(working set)를 설정한다. 워킹세트란 지역성을 기반으로 자주 사용하는 페이지를 저장해두어, 메모리에 고정하면 페이지 폴트가 빈번한 상황을 방지할 수 있다.
12. 캐시 메모리
CPU는 메모리에 접근해 데이터를 처리하는데, CPU <-> 메모리의 속도 차이를 줄이기 위해 데이터를 임시로 캐시 메모리 라는 곳에 저장한다.
CPU에서 자주 사용하는 데이터는 캐시 메모리에 따로 저장하는데, 어떤 데이터를 저장할지는 지역성(locality, CPU가 자주 참조하는 데이터가 특정 부분에 몰려있음) 을 바탕으로 결정한다.
지역성은 두가지가 있다.
- 시간 지역성(time locality) : 최근 참조한 내용을 다시 참조할 가능성이 높다.
- 공간 지역성(space locality) : 실제 참조한 주소 근처의 내용을 참조할 가능성이 높다.
요약 겸 정리
프로세스와 스레드의 차이점
프로그램은 명령어 집합.
프로세스는 실행 중인 하나의 프로그램을 의미하며 실행의 단위.
스레드는 프로세스 내에서 실행되는 흐름의 단위.
프로세스는 독립적인 메모리 영역을 갖지만, 스레드는 스택 영역만 독립적이고, 다른 영역은 다른 스레드와 공유한다.
멀티 프로세스와 멀티 스레드 차이점
멀티 프로세스는 응용 프로그램 하나를 프로세스 여러개로 구성하는 것.
멀티 스레드는 한 프로세스 안에서 여러 스레드로 작업을 처리하는 것.
프로세스는 독립적이므로 자원공유와 통신시 IPC( Inter Process Communication )를 활용해야 한다.
스레드는 스택 빼고 다 공유하니까 IPC 없어도 되어 콘텍스트 스위칭 비용 절감. 하지만 동기화가 필요하다.
동시성과 병렬성
동시성은 하나의 CPU에서 작업을 번갈아 가면서 실행해 여러 작업을 처리하는 것을 의미한다.
사용자 입장에서는 동시에 처리되는 것처럼 보인다.
병렬성은 여러 코어에서 여러 작업을 처리하는 것을 의미한다. 이게 진짜 동시에 여러 작업을 실행하는 것이다.
뮤텍스와 세마포어
멀티 프로세스 환경에서 여러 프로세스 또는 스레드가 하나의 공유 자원에 접근해도 일관성을 유지하는 프로세스 동기화를 위한 상호배제 기법
뮤텍스는 락을 가진 하나의 프로세스만 임계 영역에 접근할 수 있게 함.
세마포어는 임계 영역에 특정 개수의 프로세스가 접근할 수 있게 제어함.
따라서 구현할 때 Synchronized를 사용해 임계 영역에 하나의 스레드만 접근할 수 있게 해 락의 획득 및 해제를 발생하도록 스레드 안전(하나의 자원 또는 객체에 여러 스레드가 접근해도 원하는 결과가 나옴)을 구현한다.
페이징과 세그먼테이션
비연속 메모리 할당 방식 ( 프로세스의 메모리 영역을 나눠서 메모리 공간에 저장하는 방법 )으로, 연속적으로 할당 될때 발생하는 단편화를 개선하기 위해 만들어낸 기법.
페이징은 논리 메모리 영역과 물리 메모리 영역을 같은 크기로 나눈다.
세그먼테이션은 프로세스를 논리적 단위로 분할한다.