📌 운영체제
- 실행할 프로그램에 필요한 자원을 할당하고
- 프로그램이 올바르게 실행되도록 돕는 프로그램
- 동시다발적으로 생성, 실행, 삭제되는 다양한 프로세스를 관리한다.
- 프로세스, 스레드, 프로세스 동기화, 교착 상태 해결
- 자원 접근 및 할당
- CPU(CPU 스케줄링), 메모리(페이징, 스와핑), 입출력장치
메모리 구조
- 커널 영역(Kernel)
- 운영체제의 핵심 영역
- 커널 : 운영체제의 핵심 서비스를 담당하는 부분
- 응용 프로그램이 자원에 접근하려면 운영체제에 도움을 요청(운영체제의 코드를 실행)해야 한다. -> 이중 모드로 구현
- 시스템의 모든 것을 통제하기 때문에 사용자(유저 모드)가 직접 접근이 불가능하다.
- 접근 시 system call(시스템 콜)을 통한 커널 모드 전환이 필요하다.
- 유저 영역
- 스택 영역, 힙 영역, 데이터 영역, 코드 영역
- 코드 영역
- 실행할 수 있는 코드, 기계어로 이루어진 명령어 저장
- read-only, 데이터가 아닌 CPU가 실행할 명령어가 담기기에 쓰기 금지
- 데이터 영역
- 전역 변수와 정적 변수가 저장되는 영역
- 힙 영역
- 동적할당된 변수가 저장되는 영역, 프로그래머가 직접 할당 가능
- 동적할당 : 프로그램이 실행되는 도중에 메모리를 할당하는 것. 동적할당에서 포인터가 저장되는 곳은 스택 영역이다. 메모리 사용 후, 동적할당 해제를 하지 않으면 메모리 누수(memory leak)가 발생할 수 있다.
- 스택 영역
- 함수 내에서 지역변수와 매개변수가 저장되는 영역
- 스택 영역이 생성될 때(함수 실행) 필요한 크기만큼 만들어지고, 데이터 저장
- 함수가 끝나면 스택 영역 소멸
이중 모드
- CPU가 명령어를 실행하는 모드를 크게 사용자 모드, 커널 모드로 구분하는 방식
- 사용자 모드
- 운영체제 서비스를 제공받을 수 없는 실행 모드
- 커널 영역의 코드를 실행할 수 없는 실행 모드
- 자원 접근 불가능
- 커널 모드
- 운영체제의 서비스를 제공받을 수 있는 실행 모드
- 자원 접근을 비롯한 모든 명령어 실행 가능
- 시스템 호출(시스템 콜, system call)
- 커널 모드로 전환하여 실행하기 위해 호출
- 운영체제 서비스를 제공받기 위해 커널 모드로 전환하는 방법
- 종류
- 프로세스 관리 : fork(), exit(), waitpid()
- 파일 관리 : open(), close(), read(), write()
- 디렉터리 관리 : mkdir(), rmdir()
- 파일 시스템 관리 : mount(), umount()
프로세스
- 운영체제로부터 시스템 자원을 할당받는 작업의 단위
- 메모리에 올라와 실행되고 있는 프로그램의 인스턴스
- 동적인 개념으로 실행된 프로그램을 의미한다.
- 프로세스 확인 방법
- 윈도우 : 작업 관리자
- 리눅스, macOS : ps 명령어
- 포그라운드 프로세스(Foreground process)
- 사용자가 볼 수 있는 공간에서 실행되는 프로세스
- 백그라운드 프로세스(background process)
- 사용자와 직접 상호작용이 가능한 프로세스
- 사용자와 상호작용하지 않고 정해진 일만 수행하는 프로세스 -> 데몬(daemon), 서비스(service)
프로세스 제어 블록(PCB)
- 모든 프로세스는 실행을 위해 CPU가 필요하다.
- 하지만 CPU 자원은 한정되어 있기 떄문에, 프로세스들은 돌아가면서 한정된 시간만큼 CPU를 사용해야한다.
- 프로세스를 관리하기 위해서 PCB 사용
- 프로세스 관련 정보를 저장하는 자료구조
- 대표적인 정보
- 프로세스 ID(PID)
- 특정 프로세스를 식별하기 위해 부여하는 고유 번호(ex. 학번, 사번)
- 레지스터 값
- 프로세스가 자신의 실행 차례가 오면, 이전에 사용한 레지스터 중간 값을 모두 복원한다.
- 프로그램 카운터, 스택 포인터, ..
- 프로세스 상태
- 생성(create), 준비(ready), 실행(running), 대기(waiting), 완료(terminated)
- CPU 스케줄링 정보
- 우선 순위, 최종 실행 시각, CPU 점유 시간
- 프로세스가 언제, 어떤 순서로 CPU를 할당 받을지에 대한 정보
- 메모리 정보
- 프로세스가 어느 주소에 저장되어 있는지에 대한 정보
- 페이지 테이블 정보
- 사용한 파일과 입출력장치 정보
- 프로세스 ID(PID)
문맥 교환(context switch)
- A 프로세스에서 B 프로세스로 넘어 갈 때, 어떤 작업이 수행?
- 기존 실행 프로세스가 지금까지의 중간 정보를 백업한다.
- 중간 정보 : context(문맥)
- 다음 차례가 왔을 때 실행을 재개하기 위해 저장하는 정보
- 기존 실행 프로세스 문맥을 백업하고, 새로운 프로세스 실행을 위해 문맥을 복구하는 과정
프로세스 상태
- 생성 상태(create)
- 이제 막 메모리에 적재되어 PCB를 할당 받은 상태
- 준비가 완료되면 준비 생태로
- 준비 상태(ready)
- 바로 실행 가능하지만, 순서를 기다리는 상태
- 실행 상태(running)
- CPU를 할당 받아 실행 중인 상태
- 할당 시간을 모두 사용하면,(타이머 인터럽트 발생) 준비 상태로 이동
- 실행 도중 입출력장치를 사용하면 입출력 작업이 끝날 때까지 대기 상태로
- 대기 상태(waiting)
- 프로세스가 실행 도중 입출력장치를 사용하는 경우
- 입출력 작업이 끝나면 준비 상태로 이동
- 종료 상태(terminated)
- 프로세스가 종료된 상태
- PCB 정리
스레드
- 프로세스를 구성하는 실행 흐름의 단위
- 하나의 프로세스는 하나 이상의 스레드를 가질 수 있다.
- 단일 스레드 프로세스 : 실행 흐름 1개
- 멀티 스레드 프로세스 : 실행 흐름 2개 이상, 여러 명령어 동시 실행 가능
- 스레드의 구성 요소
- 스레드 ID, 레지스터 값, 스택 등등
- 실행에 필요한 최소한의 정보를 갖고 있다.
- 같은 프로세스에 있는 스레드 끼리 자원을 공유할 수 있다.
프로세스 VS 스레드
- 프로세스는 메모리에 올라가는 프로그램으로 운영체제로부터 메모리, 주소 공간 등을 할당 받는다.
- 멀티 프로세스 환경에서는 메모리에 올라간 다양한 프로세스들이 CPU를 선점하며 진행된다.
- CPU 선점과정을 통해 PCB에 각각의 프로세스들이 실행되었던 정보들은 문맥 교환을 통해 저장된다.
- 스레드는 각 프로세스에서 실행 단위를 뜻한다. 하나의 프로세스에 여러 개의 스레드가 동작하는 것을 멀티 스레드라고 한다.
- 각각 스레드는 한 프로세스에서 힙 영역과 데이터 영역을 공유하고, 각 스레드마다 스택과 PC레지스터 값이 따로 존재한다.
- 멀티 스레드는 생성과 관리의 중복을 최소화하고, 멀티 프로세스에 비해 문맥 교환 비용이 낮다.
멀티 프로세스 vs 멀티 스레드
- 멀티 프로세스의 프로세스는 자원을 서로 공유하지 않는다.
- 프로세스 간 통신(IPC)으로, 프로세스 간에도 자원을 주고받을 수 있다.
- 멀티 스레드에서는 하나의 프로세스 자원을 스레드가 서로 공유한다.
멀티 스레드
- 장점 : 여러 프로세스를 동시에 처리하던 일을 자원과 메모리 공유로 자원 소모에 대한 비용 절감
- 또한 프로세스의 문맥 교환과 다르게 캐시 메모리를 비울 필요가 없어 속도가 빠르다.
- 단점 : 여러 자원을 공유하기 때문에, 동기화 문제를 해결하기 위한 작업 필요
-> 멀티 프로세스도 다른 프로세스가 점유하고 있는 자원에 대해 접근할 때 동기화 문제가 발생할 수 있다.
- 문재 해결 : 임계 영역으로 동시 접근 방지 -> 세마포어, 뮤텍스
CPU 스케줄링
- 운영체제가 프로세스들에게 공정하고 합리적으로 CPU 자원을 분배하는 것
- 프로세스 우선순위(priority) 에 따라 프로세스 실행 순서가 정해진다.
- 스케줄링 큐
선점(preemptive) 스케줄링
- 프로세스가 CPU를 할당받아 실행 중이어도, 운영체제가 CPU의 사용권을 선점 가능
- 처리 시간 예측이 어렵다.
- 잦은 문맥 교환으로 오버헤드 발생 가능성이 있다.
- CPU 사용 독점 문제를 막을 수 있다.
- Interrupt, I/O or Event Completion, I/O or Event Wait, Exit
비선점(non-preemptive) 스케줄링
- 프로세스가 CPU를 점유하고 있으면, 사용을 뺐을 수 없는 방식
- 필요한 문맥 교환만 일어나기 때문에 오버헤드가 상대적으로 적다.
- 처리 시간 예측이 쉽다.
- I/O or Event wait, Exit
프로세스 상태 다이어그램
- 승인(Admitted) : 프로세스 생성이 가능하여 승인된 상태
- 스케줄러 디스패치(Scheduler dispatch) : 준비 상태에 있는 프로세스 중 하나를 선택하여 실행
- 인터럽트(Interrupt) : 예외, 입출력, 이벤트 등이 발생해서 현재 실행 중인 프로세스를 준비 상태로 바꾸고, 해당 작업을 먼저 처리
- 입출력 또는 이벤트 대기(I/O or event wait) : 실행 중인 프로세스가 입출력이나 이벤트를 처리해야 하는 경우, 입출력/이벤트가 모두 끝날 때 까지 대기 상태로 만드는 것
- 입출력 또는 이벤트 완료(I/O or event completion) : 입출력/이벤트가 끝난 프로세스를 준비 상태로 전환하여 스케줄러에 의해 선택될 수 있도록 만드는 것
CPU 스케줄링 종류
- 비선점 스케줄링
- FCFS(First Come First Served) 선입 선처리 스케줄링
- 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링
- 먼저 CPU를 요청한 프로세스부터 CPU 할당
- 실행 시간이 짧은 것이 뒤로 가면 평균 대기 시간이 길어진다.
- SJF(Shortest Job First) 최단 작업 우선 스케줄링
- 수행 시간이 가장 짧다고 판단되는 작업을 먼저 수행
- FCFS 보다 평균 대기 시간 감소, 짧은 작업에 유리하다.
- FCFS(First Come First Served) 선입 선처리 스케줄링
- 선점 스케줄링
- RR(Round Roubin) 라운드 로빈
- FCFS + 타임 슬라이스(time slice) or Time Quantum
- 타임 슬라이스 : 실행의 최소 단위 시간, 각 프로세스가 CPU를 사용할 수 있는 정해진 시간
- 정해진 시간을 모두 사용해도, 프로세스가 완료되지 않으면 큐의 맨 뒤에 삽입(문맥 교환)
- Time Quantum이 크면 FCFS와 같고, 작으면 문맥 교환이 잦아져서 오버헤드 발생
- SRT(Shortest Remaining Time) 최소 잔여 시간 우선 스케줄링
- SJF + RR
- 정해진 시간만큼 CPU를 사용하고, 다음으로 CPU를 사용할 프로세스를 남은 작업 시간이 가장 적은 프로세스를 선택한다.
- Priority Scheduling(우선순위 스케줄링)
- 프로세스들에 우선순위를 부여하고, 우선순위 높은 프로세스부터 실행
- 우선순위가 같은 프로세스들은 FCFS 스케줄링
- 단점 : 우선 순위가 낮은 프로세스를 무한정 기다리는 기아(starvation) 현상
- Aging 방법으로 기아 현상 해결이 가능하다.
- Aging : 오랫동안 대시한 프로세스의 우선순위를 점차 높이는 방식
- Multilevel-Queue(다단계 큐)
- 우선순위 스케줄링이 발전된 형태
- 우선순위별로 준비 큐를 여러 개 사용하는 스케줄링 방식
- 우선순위가 가장 높은 큐에 있는 프로세스를 먼저 처리하고, 가장 높은 큐가 비어 있으면 그 다음 우선순위 큐에 있는 프로세스를 처리한다.
- 우선순위가 높은 큐는 작은 Time Quantum, 우선순위가 낮은 큐는 큰 Time Quantum
- Multilevel feedback queue(다단계 피드백 큐 스케줄링)
- 큐 간의 이동이 가능한 다단계 큐 스케줄링
- 자연스럽게 CPU 집중 프로세스의 우선순위는 상대적으로 낮아지고, 입출력 집중 프로세스의 우선순위는 높아진다.
- RR(Round Roubin) 라운드 로빈
동기화
- 프로세스들의 수행 시기를 맞추는 것
- 실행 순서 제어 : 프로세스를 올바른 순서대로 실행, reader writer problem
- reader와 writer 프로세스는 아무렇게나 실행 되면 X
- 상호 배제 : 동시 접근이 안되는 자원에 하나의 프로세스만 접근하게 하기, bank account problem
- 한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화
- ex. 계좌에 입금할 때 현재 잔액 + 추가 금액
- 공유 자원 : 여러 프로세스 혹은 스레드가 공유하는 자원
- ex. 전역 변수, 파일, 입출력장치, 보조기억 장치 등등
- 임계 구역 : 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
- ex. 총합 변수, 잔액 변수
- 레이스 컨디션(race condition) : 임계 구역에 동시에 접근하면 자원의 일관성이 꺠지는 것
Race Condition
- 공유 자원에 대해 여러 프로세스가 동시에 접근할 때, 결과값에 영향을 줄 수 있는 상태
동기화 기법
- 뮤텍스 락, 세마포어, 모니터
- 뮤텍스 락
- 상호 배제를 위한 동기화 도구, key를 기반으로 상호 배제
- 전역 변수 1개, 함수 2개로 구현
- 자물쇠 역할 : 프로세스들이 공유하는 전역 변수 lock
- 임계 구역을 잠그는 역할 : acquire 함수
- 임계 구역의 잠금을 해제하는 역할 : release 함수
- busy waiting(바쁜 대기) 적용 : 임계 구역이 잠겨 있는지 확인하는 작업을 무한으로 작동
- 세마포어
- 일반화된 방식의 동기화 도구
- 공유 자원이 여러 개 있는 경우에도 적용 가능
- 멀티프로그래밍 환경에서 공유 자원에 대한 접근을 제한하는 방법
- 전역 변수 1개, 함수 2개로 구현
- 전역 변수 S : 임계 구역에 진입할 수 있는 프로세스 개수를 나타내는 변수
- wait 함수 : 임계구역에 들어가도 되는지, 기다려야 하는지 알려주는 함수
- signal 함수 : 임계 구역 앞에서 기다리는 프로세스에 가도 된다는 신호를 주는 함수
- busy waiting(바쁜 대기) 적용 : CPU 사이클 낭비의 단점
- 계속 반복되는 연산으로 CPU 낭비
- 해결 방법
- 사용할 수 있는 자원이 없을 경우 대기 상태로 만든다. -> 해당 프로세스의 PCB를 대기 큐에 삽입
- 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만든다. -> 해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입
wait() {
while (S <= 0) // 임계 구역에 진입할 수 있는 프로세스 개수가 0 이하면
; // 사용 가능한 자원이 있는지 확인하고
S--; // 임계 구역에 진입할 수 있는 프로세스 개수가 1개 이상이면 S 감소하고 임계 구역 진입
}
signal() {
S++; // 임계 구역에서의 작업을 마치고 S 증가
}
교착 상태(Dead lock)
- 두 개 이상의 프로세스나 스레드가 서로 자원을 얻지 못해서 다음 처리를 하지 못하는 상태
- 무한히 다음 자원을 기다리는 상태
- 교착 상태 조건
- 상호 배제 : 한 프로세스가 사용하는 자원을 다른 프로세스가 사용할 수 없는 상태
- 점유와 대기 : 자원을 할당 받은 상태에서 다른 자원을 할당 받기를 기다리는 상태
- 비선점 : 어떤 프로세스도 다른 프로세스의 자원을 강제로 빼앗지 못하는 상태
- 원형 대기 : 프로세스들이 원의 형태로 자원을 대기하는 상태
- 교착 상태 해결 방법
- 예방(prevention) : 교착 상태가 발생하지 않도록 발생 조건 중 하나를 없애기
- 회피(avoidance) : 예방보다 덜 엄격한 제약 조건으로 자원을 좀 더 효율적으로 사용할 수 있도록 해결
- 은행원 알고리즘 : 프로세스가 자원을 요구할 때, 시스템은 자원을 할당한 후에도 안정 상태인지 사전에 검사하여 교착 상태 회피
- 회복 : 교착 상태 발생을 인정하고 사후에 조치하는 방식
- 선점을 통한 회복, 프로세스 강제 종료를 통한 회복
- 무시 : 교착 상태를 해결할 때, 문맥 교환에 의한 오버헤드로 성능저하가 일어날 수 있어서 무시하는 방법
메모리 단편화
- 단편화(fragmentation) : 프로세스들이 메모리에 적재되고 해제되는 것이 반복되면, 프로세스들 사이에 사용 못하는 공간이 생긴다.
- 외부 단편화 : 메모리 공간 중 사용하지 못하게 되는 일부 물리 메모리 사이에 남는 공간들을 합쳤을 때 다른 프로세스를 할당할 수 있는 문제
- 내부 단편화 : 프로세스가 사용하는 메모리 공간 내에 사용하지 않는 부분
페이징
- 페이징 기법으로 논리 메모리는 물리 메모리에 저장될 때 연속되어 저장될 필요 없이 물리 메모리의 남는 프레임에 적절히 배치
- 페이지와 프레임을 대응하는 페이징 테이블 필요(paging table)
- 장점 : 외부 단편화를 해결
- 단점 : 내부 단편화 비중이 늘어난다.
세그멘테이션
- 페이징처럼 논리, 물리 메모리를 같은 크기의 블록이 아닌 서로 다른 크기의 논리적 단위인 세그먼트로 분할해서 할당
- 각 세그먼트는 연속적인 공간에 저장된다.
- mapping을 위한 segment table 필요
- 필요한 메모리 공간만큼 메모리를 할당하기 때문에 내부 단편화 문제는 없지만, 중간에 메모리를 해제하면 외부 단편화 발생
'CS > 운영체제' 카테고리의 다른 글
[운영체제] Swap memory 스왑 메모리 (1) | 2023.12.19 |
---|---|
[운영체제] 운영체제란?(Operating System, OS) (0) | 2022.07.04 |